def __attrs_post_init__(self): # type: () -> None self._screenshot_type = update_screenshot_type( self._screenshot_type, self._image, self._driver ) position_provider = eyes_selenium_utils.get_cur_position_provider(self._driver) if not self._driver.is_mobile_app: self._frame_chain = self._driver.frame_chain.clone() frame_size = self.get_frame_size(position_provider) self._current_frame_scroll_position = eyes_selenium_utils.get_updated_scroll_position( # noqa position_provider ) self.updated_frame_location_in_screenshot( self._frame_location_in_screenshot ) logger.debug("Calculating frame window...") self.frame_window = Region.from_( self._frame_location_in_screenshot, frame_size ) else: self._frame_chain = FrameChain() self._current_frame_scroll_position = Point.ZERO() self._frame_location_in_screenshot = Point.ZERO() self.frame_window = Region.from_( self._frame_location_in_screenshot, self.image ) self.frame_window = self.frame_window.intersect(Region.from_(self.image))
def parse_location_string(position): # type: (Union[Text, Dict]) -> Point if isinstance(position, dict): return Point.from_(position) xy = position.split(";") if len(xy) != 2: raise WebDriverException("Could not get scroll position!") return Point(round(float(xy[0])), round(float(xy[1])))
def get_updated_scroll_position(position_provider): # type: (SeleniumPositionProvider) -> Point try: sp = position_provider.get_current_position() if not sp: sp = Point.zero() except WebDriverException: sp = Point.zero() return sp
def create_entire_frame(cls, driver, image, entire_frame_size): # type: (EyesWebDriver, Image.Image, RectangleSize) -> EyesWebDriverScreenshot return cls( driver, image, ScreenshotType.ENTIRE_FRAME, frame_location_in_screenshot=Point(0, 0), current_frame_scroll_position=Point(0, 0), frame_window=Region.from_(Point(0, 0), entire_frame_size), )
def from_screenshot(cls, driver, image, screenshot_region): # type: (EyesWebDriver, Image.Image, Region) -> EyesWebDriverScreenshot return cls( driver, image, ScreenshotType.ENTIRE_FRAME, Point.ZERO(), frame_window=Region.from_(Point.ZERO(), screenshot_region.size), region_window=Region.from_(screenshot_region), )
def _region_from_element(element, screenshot): location = element.location size = element.size if screenshot: # Element's coordinates are context relative, so we need to convert them first. adjusted_location = screenshot.location_in_screenshot( Point(location["x"], location["y"]), CoordinatesType.CONTEXT_RELATIVE) else: adjusted_location = Point(location["x"], location["y"]) region = Region.from_location_size(adjusted_location, size) return region
def set_position(self, location): if self._element: element_location = self._element.location # scroll to element if Point.from_(location) == element_location: # hide header which hides actual element self._driver.execute_script( "arguments[0].style.transform='translate(0px,0px)';", self._scroll_root_element, ) return Point.from_(element_location) return super(CSSMobileSafariPositionProvider, self).set_position(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 current_scroll = eyes_selenium_utils.get_current_position( self.driver, self.driver.find_element_by_tag_name("html") ) assert current_scroll == Point(0, 0)
def create_entire_element( cls, driver, # type: EyesWebDriver image, # type: Image.Image entire_element_size, # type: RectangleSize frame_location_in_screenshot, # type: Point ): # type: (...) -> EyesWebDriverScreenshot return cls( driver, image, ScreenshotType.ENTIRE_FRAME, frame_location_in_screenshot, current_frame_scroll_position=Point(0, 0), frame_window=Region.from_(Point(0, 0), entire_element_size), )
def get_text(self, *regions): # type: (*OCRRegion) -> List[Text] result = [] for ocr_region in regions: self._process_app_output(ocr_region) image = ocr_region.app_output_with_screenshot.screenshot.image screenshot_url = self._server_connector.try_upload_image( image_utils.get_bytes(image)) data = TextSettingsData( app_output=AppOutput( screenshot_url=screenshot_url, location=Point.ZERO(), dom_url=ocr_region.app_output_with_screenshot.app_output. dom_url, ), language=ocr_region._language, min_match=ocr_region._min_match, regions=[ ExpectedTextRegion( 0, 0, width=image.width, height=image.height, expected=ocr_region._hint, ) ], ) result.extend( self._server_connector.get_text_in_running_session_image(data)) return result
def find_pattern(image, pattern): # type: (Image, Pattern) -> Optional[Point] image = image.convert("RGB") for y in range(image.height // 2): # Look for pattern in top left quadrant only for x in range(image.width // 2): if _is_pattern(image, x, y, pattern): return Point(x - pattern.offset, y - pattern.offset)
def convert_location(self, location, from_, to): # noqa: C901 # type: (Point, CoordinatesType, CoordinatesType) -> Point argument_guard.not_none(location) argument_guard.not_none(from_) argument_guard.not_none(to) result = Point.from_(location) if from_ == to: return result # If we're not inside a frame, and the screenshot is the entire # page, then the context as-is/relative are the same (notice # screenshot as-is might be different, e.g., # if it is actually a sub-screenshot of a region). if (len(self.frame_chain) == 0 and self._screenshot_type == ScreenshotType.ENTIRE_FRAME): if (from_ == self.CONTEXT_RELATIVE or from_ == self.CONTEXT_AS_IS) and to == self.SCREENSHOT_AS_IS: # If this is not a sub-screenshot, this will have no effect. result = result.offset(self._frame_location_in_screenshot) # If this is not a region subscreenshot, this will have no effect. result = result.offset(-self.region_window.left, -self.region_window.top) elif from_ == self.SCREENSHOT_AS_IS and ( to == self.CONTEXT_RELATIVE or to == self.CONTEXT_AS_IS): result = result.offset(-self._frame_location_in_screenshot) return result if from_ == self.CONTEXT_AS_IS: if to == self.CONTEXT_RELATIVE: result = result.offset(self._current_frame_scroll_position) elif to == self.SCREENSHOT_AS_IS: result = result.offset(self._frame_location_in_screenshot) else: raise CoordinatesTypeConversionError(from_, to) elif from_ == self.CONTEXT_RELATIVE: if to == self.SCREENSHOT_AS_IS: # First, convert context-relative to context-as-is. result = result.offset(-self._current_frame_scroll_position) # Now convert context-as-is to screenshot-as-is result = result.offset(self._frame_location_in_screenshot) elif to == self.CONTEXT_AS_IS: result = result.offset(-self._current_frame_scroll_position) else: raise CoordinatesTypeConversionError(from_, to) elif from_ == self.SCREENSHOT_AS_IS: if to == self.CONTEXT_RELATIVE: # First, convert context-relative to context-as-is. result = result.offset(-self._frame_location_in_screenshot) # Now convert context-as-is to screenshot-as-is result = result.offset(self._current_frame_scroll_position) elif to == self.CONTEXT_AS_IS: result = result.offset(-self._frame_location_in_screenshot) else: raise CoordinatesTypeConversionError(from_, to) else: raise CoordinatesTypeConversionError(from_, to) return result
def get_updated_frame_location_in_screenshot(self, frame_location_in_screenshot): # type: (Point) -> Point if self.frame_chain.size > 0: frame_location_in_screenshot = calc_frame_location_in_screenshot( self._driver, self._frame_chain, self._screenshot_type ) elif not frame_location_in_screenshot: frame_location_in_screenshot = Point.zero() return frame_location_in_screenshot
def updated_frame_location_in_screenshot(self, location): # type: (Point) -> None if location is None: if self.frame_chain.size > 0: self._frame_location_in_screenshot = calc_frame_location_in_screenshot( self._driver, self._frame_chain, self._screenshot_type) else: self._frame_location_in_screenshot = Point.ZERO() else: self._frame_location_in_screenshot = location
def from_screenshot(cls, driver, image, screenshot_region, frame_location_in_parent_screenshot): # type: (EyesWebDriver, Image.Image, Region, Point) -> EyesWebDriverScreenshot return cls( driver, image, ScreenshotType.ENTIRE_FRAME, frame_location_in_parent_screenshot - screenshot_region.location, frame_window=Region.from_(Point.ZERO(), screenshot_region.size), )
def test_mobilesafariwebelement(eyes, driver_mock, eyes_element_mock): eyes.configure.is_simulator = True eyes_element_mock.element.location = Point(0, 10) eyes_element_mock.element.rect = dict(x=0, y=0, width=600, height=400) driver_mock.user_agent = UserAgent(os="iOS", browser="Mobile Safari") mobile_safari_element = adapt_element(eyes_element_mock) with patch( "applitools.selenium.webelement.eyes_selenium_utils.get_current_position", return_value=Point(0, 50), ): assert mobile_safari_element.location == Point(0, 60) assert mobile_safari_element.rect == dict(x=0, y=60, width=600, height=400) assert mobile_safari_element.bounds == Region( 0, 60, 1, 1, CoordinatesType.CONTEXT_RELATIVE)
def calc_frame_location_in_screenshot(driver, frame_chain, screenshot_type): window_scroll = eyes_selenium_utils.get_default_content_scroll_position( frame_chain, driver) logger.info("Getting first frame...") first_frame = frame_chain[0] location_in_screenshot = Point.from_(first_frame.location) # 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 screenshot_type == ScreenshotType.VIEWPORT: location_in_screenshot = location_in_screenshot.offset( Point(-window_scroll.x, 0)) # For inner frames we must calculate the scroll inner_frames = frame_chain[1:] for frame in inner_frames: location_in_screenshot = location_in_screenshot.offset( frame.location - frame.parent_scroll_position) return location_in_screenshot
def get_app_output(): scale_provider = self._eyes.update_scaling_params() viewport_screenshot = self._eyes.get_scaled_cropped_viewport_image( scale_provider) image = image_utils.get_bytes(viewport_screenshot) screenshot_url = self._server_connector.try_upload_image(image) dom_json = self._eyes._try_capture_dom() dom_url = self._eyes._try_post_dom_capture(dom_json) return AppOutput(dom_url=dom_url, screenshot_url=screenshot_url, location=Point.ZERO())
def get_current_position(self): # type: () -> Point """ The scroll position of the current frame. """ if self._driver.is_mobile_web: x, y = self._driver.execute_script( self._JS_GET_CURRENT_SCROLL_POSITION, self._scroll_root_element ) if x is None or y is None: raise EyesError("Got None as scroll position! ({},{})".format(x, y)) return Point(x, y) return self.get_current_position_static(self._driver, self._scroll_root_element)
def get_current_position(self): position = Point(self._element.get_scroll_left(), self._element.get_scroll_top()) logger.debug("Current position: {}".format(position)) return position
def __init__(self, driver, scroll_root_element): # type: (EyesWebDriver, AnyWebElement) -> None self._last_set_position = Point.ZERO() super(CSSTranslatePositionProvider, self).__init__(driver, scroll_root_element)
def create_viewport(cls, driver, image): # type: (EyesWebDriver, Image.Image) -> EyesWebDriverScreenshot instance = cls(driver, image, ScreenshotType.VIEWPORT, Point.zero()) instance._validate_frame_window() return instance
1, 2.6, 3.5, 4.1, CoordinatesType.SCREENSHOT_AS_IS, Region(1, 3, 4, 4, CoordinatesType.SCREENSHOT_AS_IS), ], ], ) def test_region_creation(left, top, width, height, coord_type, result): expect = Region(left, top, width, height, coord_type) assert expect == result @pytest.mark.parametrize( "x,y,result", [[0, 0, Point(0, 0)], [1.6, 2.2, Point(2, 2)]], ) def test_point_creation(x, y, result): expect = Point(x, y) assert expect == result @pytest.mark.parametrize( "width,height,result", [[0, 0, RectangleSize(0, 0)], [1.6, 2.2, RectangleSize(2, 2)]], ) def test_rectangle_size_creation(width, height, result): expect = RectangleSize(width, height) assert expect == result
def get_stitched_region(self, region, full_area, position_provider): # type: (Region, Optional[Region], Optional[PositionProvider]) -> Image.Image argument_guard.not_none(region) argument_guard.not_none(position_provider) logger.info( "region: %s ; full_area: %s ; position_provider: %s" % (region, full_area, position_provider.__class__.__name__) ) origin_state = self.origin_provider.get_state() if self.origin_provider != position_provider: self.origin_provider.set_position( Point.ZERO() ) # first scroll to 0,0 so CSS stitching works. # Saving the original position (in case we were already in the outermost frame). original_stitched_state = position_provider.get_state() datetime_utils.sleep(self.wait_before_screenshots) initial_screenshot = self.image_provider.get_image() initial_size = RectangleSize.from_(initial_screenshot) pixel_ratio = self._get_pixel_ratio(initial_screenshot) scaled_cut_provider = self.cut_provider.scale(pixel_ratio) cutted_initial_screenshot = self._cut_if_needed( initial_screenshot, scaled_cut_provider ) self.debug_screenshot_provider.save( cutted_initial_screenshot, self._debug_msg("cutted_initial_screenshot") ) region_in_initial_screenshot = self._get_region_in_screenshot( region, cutted_initial_screenshot, pixel_ratio ) cropped_initial_screenshot = self._crop_if_needed( cutted_initial_screenshot, region_in_initial_screenshot ) self.debug_screenshot_provider.save( cropped_initial_screenshot, self._debug_msg("cropped_initial_screenshot") ) scaled_initial_screenshot = image_utils.scale_image( cropped_initial_screenshot, self.scale_provider ) self.debug_screenshot_provider.save( scaled_initial_screenshot, self._debug_msg("scaled_initial_screenshot") ) if full_area is None or full_area.is_empty: entire_size = self._get_entire_size(initial_screenshot, position_provider) # Notice that this might still happen even if we used # "get_image_part", since "entire_page_size" might be that of a # frame if ( scaled_initial_screenshot.width >= entire_size.width and scaled_initial_screenshot.height >= entire_size.height ): self.origin_provider.restore_state(origin_state) return scaled_initial_screenshot full_area = Region.from_(Point.ZERO(), entire_size) scaled_cropped_location = full_area.location physical_crop_location = Point.from_(scaled_cropped_location).scale(pixel_ratio) if region_in_initial_screenshot.is_empty: physical_crop_size = RectangleSize( initial_size.width - physical_crop_location.x, initial_size.height - physical_crop_location.y, ) source_region = Region.from_(physical_crop_location, physical_crop_size) else: # Starting with the screenshot we already captured at (0,0). source_region = region_in_initial_screenshot scaled_cropped_source_rect = self.cut_provider.to_region(source_region.size) scaled_cropped_source_rect = scaled_cropped_source_rect.offset( source_region.left, source_region.top ) scaled_cropped_source_region = dict( x=int(math.ceil(scaled_cropped_source_rect.left / pixel_ratio)), y=int(math.ceil(scaled_cropped_source_rect.top / pixel_ratio)), width=int(math.ceil(scaled_cropped_source_rect.width / pixel_ratio)), height=int(math.ceil(scaled_cropped_source_rect.height / pixel_ratio)), ) scaled_cropped_size = dict( width=scaled_cropped_source_region["width"], height=scaled_cropped_source_region["height"], ) # Getting the list of viewport regions composing the page # (we'll take screenshot for each one). if region_in_initial_screenshot.is_empty: x = max(0, full_area.left) y = max(0, full_area.top) w = min(full_area.width, scaled_cropped_size["width"]) h = min(full_area.height, scaled_cropped_size["height"]) rect_in_initial_screenshot = Region( round(x * pixel_ratio), round(y * pixel_ratio), round(w * pixel_ratio), round(h * pixel_ratio), ) else: rect_in_initial_screenshot = region_in_initial_screenshot screenshot_parts = self._get_image_parts( full_area, scaled_cropped_size, pixel_ratio, rect_in_initial_screenshot ) # Starting with element region size part of the screenshot. Use it as a size # template. stitched_image = Image.new("RGBA", (full_area.width, full_area.height)) # Take screenshot and stitch for each screenshot part. stitched_image = self._stitch_screenshot( original_stitched_state, position_provider, screenshot_parts, stitched_image, self.scale_provider.scale_ratio, scaled_cut_provider, ) position_provider.restore_state(original_stitched_state) self.origin_provider.restore_state(origin_state) return stitched_image
def parse_location_string(position): # type: (Text) -> Point xy = position.split(";") if len(xy) != 2: raise WebDriverException("Could not get scroll position!") return Point(round(float(xy[0])), round(float(xy[1])))
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.ZERO() for frame in self: location = location.offset(frame.location) return location
], [ 1, 2.6, 3.5, 4.1, CoordinatesType.SCREENSHOT_AS_IS, Region(1, 3, 4, 4, CoordinatesType.SCREENSHOT_AS_IS), ], ], ) def test_region_creation(left, top, width, height, coord_type, result): expect = Region(left, top, width, height, coord_type) assert expect == result @pytest.mark.parametrize( "x,y,result", [[0, 0, Point(0, 0)], [1.6, 2.2, Point(2, 2)]]) def test_point_creation(x, y, result): expect = Point(x, y) assert expect == result @pytest.mark.parametrize( "width,height,result", [[0, 0, RectangleSize(0, 0)], [1.6, 2.2, RectangleSize(2, 2)]], ) def test_rectangle_size_creation(width, height, result): expect = RectangleSize(width, height) assert expect == result
def test_paste_image_no_error_if_point_has_float_values(image): point = Point(0, 0) point.x = 3.4 point.x = 5.6 image_utils.paste_image(image, image, point)
def test_point_creation(x, y, result): expect = Point(x, y) assert expect == result