def parse_gap_options(driver: selenium.webdriver.Remote, gap_index: int) -> Dict[str, Decimal]: options = dict() seen = set() while True: try: answer = driver.find_element_by_id("gap_%d[answer][%d]" % (gap_index, len(options))) except NoSuchElementException: break points = driver.find_element_by_id("gap_%d[points][%d]" % (gap_index, len(options))) answer_key = answer.get_attribute("value") if answer_key.strip() in seen: raise InteractionException( "the gap has multiple identical options named '%s'. unsupported." % answer_key) seen.add(answer_key.strip()) options[answer_key] = Decimal(points.get_attribute("value")) return options
def interact(driver: selenium.webdriver.Remote, action: Callable[[], Any], refresh: bool = False) -> Any: n_retries = 5 while True: try: return action() except (WebDriverException, SessionNotCreatedException): if n_retries < 1: raise n_retries -= 1 if refresh: with wait_for_page_load(driver): driver.refresh()
def parse_numeric_gap_scoring(driver: selenium.webdriver.Remote, gap_index: int) -> Dict: value = Decimal( driver.find_element_by_name("gap_%d_numeric" % gap_index).get_attribute("value")) lower = Decimal( driver.find_element_by_name("gap_%d_numeric_lower" % gap_index).get_attribute("value")) upper = Decimal( driver.find_element_by_name("gap_%d_numeric_upper" % gap_index).get_attribute("value")) score = Decimal( driver.find_element_by_name("gap_%d_numeric_points" % gap_index).get_attribute("value")) return dict(value=value, lower=lower, upper=upper, score=score)
def _create_result_with_details(self, driver: selenium.webdriver.Remote, report: Callable[[str], None], e: Exception, trace: str): files = dict() files['error/trace.txt'] = trace.encode('utf8') url, html, alert = get_driver_error_details(driver) if alert: files['error/alert.txt'] = alert.encode('utf8') if html: files['error/page.html'] = html.encode('utf8') try: files['error/screen.png'] = base64.b64decode( driver.get_screenshot_as_base64()) except: traceback.print_exc() filenames = map(lambda s: '%s_%s' % (self.username, s), files.keys()) error = 'test failed on url %s. for details, see %s.' % ( url, ', '.join(filenames)) report(error) return Result.from_error(Origin.recorded, e.get_error_domain(), error, files)
def getConsoleLog(driver: selenium.webdriver.Remote, clear:bool=False): """ :param clear: also clears the array :return: all logs since the start of the capturing or from last clear.""" script = "return window.alllog;" if clear: script = "var temp = window.alllog; window.alllog = []; return temp;" return driver.execute_script(script)
def _update_from_readjustment_ui(driver: selenium.webdriver.Remote, scoring: ClozeScoring, context: 'TestDriver'): if context.ilias_version < (5, 4): return ClozeQuestion._get_ui(driver) else: with wait_for_page_load(driver): # go to readjustment scoring tab driver.find_element_by_id("tab_question").click() readjusters = ClozeQuestion._create_readjusters( driver, scoring, context) # update option texts we might have missed so far. gaps = [] for gap_index, gap in enumerate(scoring.gaps): gaps.append(readjusters[gap_index].update_gap(gap)) return scoring._replace(gaps=gaps)
def selectThroughSR(driver: selenium.webdriver.Remote, *selectors: str, analyseError: bool = True, onlyTry: bool = False, origin: WebElement = None, allLast: bool = False) -> WebElement: """ Select elements according to the DOM shadow-roots :param driver: the driver to use (can be null if origin is given) :param selectors: the CSS selectors (add ! prefix in order to not go inside the shadow-root - the last one do not go inside the shadow-root anyway) :param analyseError: internal option, allow looking at which element there was an error :param onlyTry: do not return anything (use for testing if element chain is present) :param origin: (optional) root of the search :param allLast: return all end elements found :return: the found element(s) """ # select element through shadow roots try: args = [] script = "var el = document;\n" if origin is not None: # origin is specified script = "var el = arguments[0];\n" args.append(origin) if driver is None: driver = origin.parent for i, selector in enumerate(selectors): if i == len(selectors) - 1 and allLast: script += 'el = el.querySelectorAll("%s");\n' % selector; else: if selector.startswith("!"): script += 'el = el.querySelector("%s");\n' % selector[1:]; else: script += 'el = el.querySelector("%s"); if (el.shadowRoot) el = el.shadowRoot;\n' % selector; if not onlyTry: script += "return el;" #print(script) return driver.execute_script(script, *args) except Exception as err: if analyseError: for i in range(1, len(selectors)+1): try: selectThroughSR(driver, *selectors[:i], analyseError=False, onlyTry=True, origin=origin) except: raise Exception("Error {!r} for {}".format(err, selectors[:i])) else: # no error, probably because error during "return el;" raise else: raise
def _set_ui(driver: selenium.webdriver.Remote, scoring: ClozeScoring, context: 'TestContext'): readjusters = ClozeQuestion._create_readjusters( driver, scoring, context) if context.ilias_version >= (5, 4): with wait_for_page_load(driver): # go to readjustment statistics ("given answers") tab driver.find_element_by_id("tab_answers").click() # add new scored answers. for gap_index, gap in enumerate(scoring.gaps): readjusters[gap_index].extend_scores() if context.ilias_version >= (5, 4): for t in range(3): try: with wait_for_page_load(driver): # go to readjustment scoring tab driver.find_element_by_id("tab_question").click() break except: driver.refresh() # we're now on the main tab (scoring tab) and stay there. this is important as # the save only happens in our caller and we would lose all data if we switched # to another tab without saving. if context.ilias_version < (5, 4): identical_scoring_checkbox = driver.find_element_by_name( "identical_scoring") if identical_scoring_checkbox.is_selected( ) != scoring.identical_scoring: identical_scoring_checkbox.click() Select( driver.find_element_by_id("textgap_rating")).select_by_value( scoring.comparator.value) # update scores. for gap_index, gap in enumerate(scoring.gaps): readjusters[gap_index].update_scores()
def _configure_driver(driver: selenium.webdriver.Remote, resolution: str): try: # we try to avoid the need to scroll. a large size can cause memory issues. w = 1024 h = 1024 if resolution is not None and isinstance(resolution, str): w, h = resolution.split('x') w = int(w) h = int(h) driver.set_window_size(w, h) driver.set_page_load_timeout(30) except: driver.quit() raise
def _get_ui(driver: selenium.webdriver.Remote) -> ClozeScoring: fixed_text_length = driver.find_element_by_name( "fixedTextLength").get_attribute("value").strip() if fixed_text_length == '': fixed_text_length = None else: fixed_text_length = int(fixed_text_length) gaps = list() while True: gap_index = len(gaps) try: cloze_type_element = driver.find_element_by_name( "clozetype_%d" % gap_index) except NoSuchElementException: break cloze_type = ClozeType( int(cloze_type_element.get_attribute("value"))) if cloze_type != ClozeType.select: gap_size = parse_gap_size(driver, gap_index) if gap_size is None: gap_size = fixed_text_length else: gap_size = None if cloze_type in (ClozeType.text, ClozeType.select): options = parse_gap_options(driver, gap_index) if not options: raise InteractionException( "did not find gap options (%d)" % gap_index) scoring = TextualGapScoring(cloze_type=cloze_type, size=gap_size, options=options) elif cloze_type == ClozeType.numeric: scoring = NumericGapScoring(cloze_type=ClozeType.numeric, **parse_numeric_gap_scoring( driver, gap_index)) else: raise NotImplementedException("unsupported cloze type " + str(cloze_type)) gaps.append(scoring) identical_scoring = driver.find_element_by_name( "identical_scoring").is_selected() comparator = ClozeComparator( driver.find_element_by_css_selector( "#textgap_rating option[selected]").get_attribute("value")) return ClozeScoring(identical_scoring=identical_scoring, comparator=comparator, gaps=gaps)
def setAttribute(driver: selenium.webdriver.Remote, element: WebElement, attribute: str, value: str): """Set an attribute value""" driver.execute_script("arguments[0].setAttribute(arguments[1], arguments[2]);", element, attribute, value)
def clearConsoleLog(driver: selenium.webdriver.Remote): """Clears the remote log storage.""" return driver.execute_script("window.alllog = [];")
def captureConsoleLog(driver: selenium.webdriver.Remote): """Start capturing the console.log calls.""" driver.execute_script("window.alllog = []; var old_console_log = console.log; console.log = function() {window.alllog.push(arguments);old_console_log.apply(null, arguments);};")