def push_state(self): """ Adds the transform to the states list. """ transforms = self._get_current_transform() if not all(transforms.values()): self._current_position = Point.create_top_left() else: point = Point(0, 0) for transform in transforms.values(): point += self._get_position_from_transform(transform) self._current_position = point self._states.append(self._current_position)
def get_current_position(self): try: x, y = self._execute_script(self._JS_GET_CURRENT_SCROLL_POSITION) if x is None or y is None: raise EyesError("Got None as scroll position! ({},{})".format(x, y)) except WebDriverException: raise EyesError("Failed to extract current scroll position!") return Point(x, y)
class CSSTranslatePositionProvider(SeleniumPositionProvider): _JS_TRANSFORM_KEYS = ["transform", "-webkit-transform"] def __init__(self, driver): super(CSSTranslatePositionProvider, self).__init__(driver) self._current_position = Point(0, 0) def _set_transform(self, transform_list): script = '' for key, value in transform_list.items(): script += "document.documentElement.style['{}'] = '{}';".format(key, value) self._execute_script(script) def _get_current_transform(self): script = 'return {' for key in self._JS_TRANSFORM_KEYS: script += "'{0}': document.documentElement.style['{0}'],".format(key) script += ' }' return self._execute_script(script) def get_current_position(self): return self._current_position.clone() def _get_position_from_transform(self, transform): data = re.match(r"^translate\(\s*(\-?)([\d, \.]+)px,\s*(\-?)([\d, \.]+)px\s*\)", transform) if not data: raise EyesError("Can't parse CSS transition") x = float(data.group(2)) y = float(data.group(4)) minus_x, minus_y = data.group(1), data.group(3) if minus_x: x *= -1 if minus_y: y *= -1 return Point(float(x), float(y)) def set_position(self, location): translate_command = "translate(-{}px, -{}px)".format(location.x, location.y) logger.debug(translate_command) transform_list = dict((key, translate_command) for key in self._JS_TRANSFORM_KEYS) self._set_transform(transform_list) self._current_position = location.clone() def push_state(self): """ Adds the transform to the states list. """ transforms = self._get_current_transform() if not all(transforms.values()): self._current_position = Point.create_top_left() else: point = Point(0, 0) for transform in transforms.values(): point += self._get_position_from_transform(transform) self._current_position = point self._states.append(self._current_position)
def __init__(self, image, location=None): super(EyesImagesScreenshot, self).__init__(image) if location is None: location = Point.create_top_left() argument_guard.is_a(location, Point) self._location = location self._bounds = Region.from_location_size( location, dict(width=self._image.width, height=self._image.height) )
def get_full_window_dom(driver, position_provider=None): # type: (EyesWebDriver, PositionProvider) -> str if position_provider: position_provider.push_state() position_provider.set_position(Point.create_top_left()) dom = _get_window_dom(driver) dom_json = json.dumps(dom) if position_provider: position_provider.pop_state() return dom_json
def _get_position_from_transform(self, transform): data = re.match(r"^translate\(\s*(\-?)([\d, \.]+)px,\s*(\-?)([\d, \.]+)px\s*\)", transform) if not data: raise EyesError("Can't parse CSS transition") x = float(data.group(2)) y = float(data.group(4)) minus_x, minus_y = data.group(1), data.group(3) if minus_x: x *= -1 if minus_y: y *= -1 return Point(float(x), float(y))
def get_sub_screenshot_by_region(self, region): sub_screenshot_region = self.get_intersected_region(region) if sub_screenshot_region.is_empty: raise OutOfBoundsError("Region {0} is out of bounds!".format(region)) # If we take a screenshot of a region inside a frame, then the frame's (0,0) is in the # negative offset of the region.. sub_screenshot_frame_location = Point(-region.left, -region.top) # FIXME Calculate relative region location? (same as the java version) screenshot = image_utils.get_image_part(self._screenshot, sub_screenshot_region) return EyesWebDriverScreenshot( self._driver, screenshot, is_viewport_screenshot=self._is_viewport_screenshot, frame_location_in_screenshot=sub_screenshot_frame_location, )
def calc_frame_location_in_screenshot(frame_chain, is_viewport_screenshot): first_frame = frame_chain[0] location_in_screenshot = Point(first_frame.location['x'], first_frame.location['y']) # We only need to consider the scroll of the default content if the screenshot is a # viewport screenshot. If this is a full page screenshot, the frame location will not # change anyway. if is_viewport_screenshot: location_in_screenshot.x -= first_frame.parent_scroll_position.x location_in_screenshot.y -= first_frame.parent_scroll_position.y # For inner frames we must calculate the scroll inner_frames = frame_chain[1:] for frame in inner_frames: location_in_screenshot.x += frame.location[ 'x'] - frame.parent_scroll_position.x location_in_screenshot.y += frame.location[ 'y'] - frame.parent_scroll_position.y return location_in_screenshot
def __init__(self, driver): super(CSSTranslatePositionProvider, self).__init__(driver) self._current_position = Point(0, 0)
def get_current_position(self): position = Point( self._element.get_scroll_left(), self._element.get_scroll_top() ) logger.info("Current position: {}".format(position)) return position
def __init__(self, driver, screenshot=None, screenshot64=None, is_viewport_screenshot=None, frame_location_in_screenshot=None): # type: (EyesWebDriver, Image.Image, None, tp.Optional[bool], tp.Optional[Point]) -> None """ Initializes a Screenshot instance. Either screenshot or screenshot64 must NOT be None. Should not be used directly. Use create_from_image/create_from_base64 instead. :param driver: EyesWebDriver instance which handles the session from which the screenshot was retrieved. :param screenshot: image instance. If screenshot64 is None, this variable must NOT be none. :param screenshot64: The base64 representation of a png image. If screenshot is None, this variable must NOT be none. :param is_viewport_screenshot: Whether the screenshot object represents a viewport screenshot or a full screenshot. :param frame_location_in_screenshot: The location of the frame relative to the top,left of the screenshot. :raise EyesError: If the screenshots are None. """ if screenshot is None and screenshot64 is None: raise EyesError("both screenshot and screenshot64 are None!") if screenshot64: screenshot = image_utils.image_from_bytes( base64.b64decode(screenshot64)) # initializing of screenshot super(EyesWebDriverScreenshot, self).__init__(image=screenshot) self._driver = driver self._viewport_size = driver.get_default_content_viewport_size( force_query=False) # type: ViewPort self._frame_chain = driver.frame_chain.clone() if self._frame_chain: chain_len = len(self._frame_chain) self._frame_size = self._frame_chain[chain_len - 1].outer_size else: try: self._frame_size = driver.get_entire_page_size() except WebDriverException: # For Appium, we can't get the "entire page size", so we use the viewport size. self._frame_size = self._viewport_size # For native Appium Apps we can't get the scroll position, so we use (0,0) try: self._scroll_position = driver.get_current_position() except (WebDriverException, EyesError): self._scroll_position = Point(0, 0) if is_viewport_screenshot is None: is_viewport_screenshot = ( self._screenshot.width <= self._viewport_size['width'] and self._screenshot.height <= self._viewport_size['height']) self._is_viewport_screenshot = is_viewport_screenshot if frame_location_in_screenshot is None: if self._frame_chain: frame_location_in_screenshot = EyesWebDriverScreenshot \ .calc_frame_location_in_screenshot(self._frame_chain, is_viewport_screenshot) else: # The frame is the default content frame_location_in_screenshot = Point(0, 0) if self._is_viewport_screenshot: frame_location_in_screenshot.offset( -self._scroll_position.x, -self._scroll_position.y) self._frame_location_in_screenshot = frame_location_in_screenshot self._frame_screenshot_intersect = Region( frame_location_in_screenshot.x, frame_location_in_screenshot.y, self._frame_size['width'], self._frame_size['height']) self._frame_screenshot_intersect.intersect( Region(width=self._screenshot.width, height=self._screenshot.height))
def default_content_scroll_position(self): # type: () -> tp.Union[Point, EyesError] if len(self) == 0: raise EyesError("No frames in frame chain") result = self[0].parent_scroll_position return Point(result.x, result.y)
def current_frame_offset(self): # type: () -> Point location = Point.create_top_left() for frame in self: location.offset_by_location(frame.location) return location
def test_position_scrolled_to_origin_after_traversing(self): # Page must contain scrolling dom_json = dom_capture.get_full_window_dom(self.driver) # noqa: F841 assert self.driver.get_current_position() == Point(0, 0)