import NAVIGATION_DATA from "./navigation.yml"; function interpolate(template, properties) { let parsed = template; parsed = parsed.replace("$$", "$"); // Handle escaping $ in Python style... Object.keys(properties).forEach((key) => { const value = properties[key]; parsed = parsed.replace("${" + key + "}", value); }); return parsed; } export class SelectorTemplate extends Function { constructor(selector, selectorType, props = {}, children = {}) { super(); if (selectorType == "data-description") { selectorType = "css"; selector = `[data-description="${selector}"]`; } this._selector = selector; this.selectorType = selectorType; this._props = props || {}; return new Proxy(this, { apply: (target, thisArg, args) => target._call(args), }); } _call(args) { const inputProps = args[0]; const allProps = { ...this._props, ...inputProps }; return new SelectorTemplate(this._selector, this.selectorType, allProps, this.children); } get description() { const selector = this.selector; let desc; if (this.selectorType == "css") { desc = `CSS selector [${selector}]`; } else if (this.selectorType == "xpath") { desc = `XPATH selector [${selector}]`; } else if (this.selectorType == "id") { desc = `DOM element with id [${selector}]`; } return desc; } get selector() { return interpolate(this._selector, this._props); } } function selectorTemplateFromObject(object, children = {}) { if (typeof object === "string" || object instanceof String) { const selector = object; return new SelectorTemplate(selector, "css", {}, children); } else { const selectorType = object.type || "css"; const selector = object.selector; return new SelectorTemplate(selector, selectorType, {}, children); } } function componentFromObject(name, object) { const selectors = {}; const subComponents = {}; Object.keys(object).forEach((key) => { const value = object[key]; if (key == "selectors") { let baseSelector = null; const hasBaseSelector = value["_"] !== undefined; if (hasBaseSelector) { baseSelector = value["_"]; delete value["_"]; } Object.keys(value).forEach((selectorKey) => { const selectorValue = value[selectorKey]; if (selectorValue == undefined) { throw Error(`Problem with selectors value ${selectorValue}`); } selectors[selectorKey] = selectorTemplateFromObject(selectorValue); }); if (baseSelector) { selectors["_"] = selectorTemplateFromObject(baseSelector, selectors); } } else if (key == "labels") { // implement as needed } else if (key == "text") { // implement as needed } else { const component = componentFromObject(key, value); subComponents[key] = component; } }); return new Component(name, subComponents, selectors); } export class Component { constructor(name, subComponents, selectors) { self._name = name; self._subComponents = subComponents; self._selectors = selectors; const component = this; Object.keys(subComponents).forEach((key) => { const value = subComponents[key]; component[key] = value; }); Object.keys(selectors).forEach((key) => { const value = selectors[key]; component[key] = value; }); } get selector() { if (hasOwnProperty("_")) { return this["_"]; } else { throw Error(`No _ selector for [${this}]`); } } } export const ROOT_COMPONENT = componentFromObject("root", NAVIGATION_DATA);