def __init__(self, driver): self.webdriver=driver self.parser=Parser(driver)
class Surrogate(): # History action_history = [] # record=[ <action>, <element>, <rectangle> ] # Current state element_on_focus = None # USE THIS last_successful_identifiers = None # Incapsulated parser = None webdriver = None itree = None #webpage = None lazy_bastard_cases = [ "starts-with" ] def __init__(self, driver): self.webdriver=driver self.parser=Parser(driver) # Decode API def do(self, *args): global running_identifiers action=args[0] if action=="goto": url=args[1] result=self.goto(url) elif action=="click": exprs=args[1] identifiers=self.parser.exprs_to_identifiers(exprs) running_identifiers=identifiers result=self.click(identifiers) elif action=="see": exprs=args[1] identifiers=self.parser.exprs_to_identifiers(exprs) running_identifiers=identifiers result=self.see(identifiers) elif action=="type": input=args[1] if args[2]: print "passed expressions" exprs=args[2] identifiers=self.parser.exprs_to_identifiers(exprs) running_identifiers=identifiers result=self.see(exprs) and self.type(input) else: #print "didn't pass expressions" result=self.type(input) return result # Record an action def record_action(fn): def f(self, *args): result=fn(self, *args) self.action_history+=[(fn.__name__, result)] return result return f # Take a snapshot def snapshot_on_error(fn): def f(self, *args): global screenshot_on_fatal_error screenshot_on_fatal_error=True result=fn(self, *args) screenshot_on_fatal_error=False return result return f # Click @record_action @snapshot_on_error def click(self, identifiers): uniq_el=get_uniq_webobject(self, "click", identifiers) #if uniq_el: # print uniq_el.get_css_value("class") if uniq_el: try: tabs_N_old=len(self.webdriver.window_handles) uniq_el.click() if len(self.webdriver.window_handles)>tabs_N_old: self.webdriver.switch_to_window(self.webdriver.window_handles[-1]) print("New tab opened. Will wait 2 seconds so it loads.") from time import sleep sleep(2) # MAKE SURE PAGE LOADED FIRST self.itree = ItreeBuilder().build_itree(self.webdriver) self.last_successful_identifiers=identifiers return True except WebDriverException as exception: fatal_error("Could not click on '%s'. Maybe something is in"\ "front of it?" % uniq_el.get_attribute('innerHTML')) except StaleElementReferenceException as exception: fatal_error("Element belongs to an old itree. Update the itree.") except Exception as exception: raise exception else: return False # See @record_action @snapshot_on_error def see(self, identifiers): uniq_el=get_uniq_webobject(self, "see", identifiers) if uniq_el: self.last_successful_identifiers=identifiers self.last_seen_uniq_el=uniq_el return True return False # Type @record_action @snapshot_on_error def type(self, input): uniq_el=None # Find all typeable fields #self.itree.grow_branch(0, ["typeable"], self.last_successful_identifiers) #print itree descrs=( { "tag" : "input", "attributes" : [("type", "text")] }, { "tag" : "input", "attributes" : [("type", "password")] }, { "tag" : "input", "attributes" : [("type", "search")] }, ) els_list=[] els = [] for desc in descrs: els_list.append(self.webdriver.find_elements_by_xpath(ItreeBuilder().xpath_builder.make_xpath(desc))) singletons = [els for els in els_list if len(els)==1] els = [el[0] for el in singletons] els=remove_duplicate_webobjects(els) #print els # Choose field closest to last seen anchor_el = None if self.last_seen_uniq_el: anchor_el = webobject_to_rectangle(self.last_seen_uniq_el) if len(els)>0: uniq_el=els[0] for input_field in els:#self.itree.webobjects(0, "typeable"): dist_old=anchor_el.distance_to_rect(webobject_to_rectangle(uniq_el)) dist_new=anchor_el.distance_to_rect(webobject_to_rectangle(input_field)) if dist_new<dist_old: uniq_el=input_field #NEED REFACTOR get_unique_webobject FIRST #el=self.webpage_analyzer.get_webobject_ #self.element_on_focus. if uniq_el: uniq_el.send_keys(input) return True return False def goto(self, url): try: self.webdriver.get(url) self.itree = ItreeBuilder().build_itree(self.webdriver) return True except Exception as exception: fatal_error(exception) return False