def __attrs_post_init__(self): # type: () -> None self._frame_chain = self._driver.frame_chain.clone() self._screenshot_type = update_screenshot_type( self._screenshot_type, self._image, self._driver ) cur_frame_position_provider = self._driver.eyes.current_frame_position_provider if cur_frame_position_provider: position_provider = cur_frame_position_provider else: position_provider = self._driver.eyes.position_provider if self._current_frame_scroll_position is None: self._current_frame_scroll_position = get_updated_scroll_position( position_provider ) self._frame_location_in_screenshot = self.get_updated_frame_location_in_screenshot( self._frame_location_in_screenshot ) logger.debug("Calculating frame window...") if self.frame_window is None: frame_size = self.get_frame_size(position_provider) self.frame_window = Region.from_location_size( self._frame_location_in_screenshot, frame_size ) self.frame_window.intersect( Region(0, 0, width=self.image.width, height=self.image.height) )
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_location_size(Point(0, 0), entire_frame_size), )
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 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_location_size( Point.zero(), screenshot_region.size ), region_window=Region.from_(screenshot_region), )
def _get_viewport_scroll_bounds(self): switch_to = self.driver.switch_to with switch_to.frames_and_back(self.original_frame_chain): try: location = ScrollPositionProvider.get_current_position_static( self.driver, self.scroll_root_element) except WebDriverException as e: logger.warning(str(e)) logger.info("Assuming position is 0,0") location = Point(0, 0) viewport_bounds = Region.from_location_size(location, self._get_viewport_size()) return viewport_bounds
def get_image(self): image = TakesScreenshotImageProvider(self._eyes).get_image() self._eyes.debug_screenshot_provider.save(image, "SAFARI") if self._eyes.is_cut_provider_explicitly_set: return image scale_ratio = self._eyes.device_pixel_ratio original_viewport_size = self._eyes._get_viewport_size() viewport_size = original_viewport_size.scale(scale_ratio) logger.info("logical viewport size: {}".format(original_viewport_size)) if self._useragent.os == OSNames.IOS: if self._devices_regions is None: self.init_device_regions_table() logger.info("physical device pixel size: {} x {}".format( image.width, image.height)) device_delta = DeviceData( image.width, image.height, original_viewport_size.width, original_viewport_size.height, self._useragent.browser_major_version, ) if device_delta in self._devices_regions: logger.debug("device model found in hash table") crop = self._devices_regions.get(device_delta) image = image_utils.crop_image(image, crop) else: logger.debug( "device not found in list. returning original image.") elif not self._eyes.configuration.force_full_page_screenshot: current_frame_chain = self._eyes.driver.frame_chain # type: FrameChain if len(current_frame_chain) == 0: position_provider = ScrollPositionProvider( self._eyes.driver, self._eyes.driver.find_element_by_tag_name("html"), ) loc = position_provider.get_current_position() else: loc = current_frame_chain.default_content_scroll_position loc = loc.scale(scale_ratio) image = image_utils.crop_image( image, Region.from_location_size(loc, viewport_size)) return image
def _ensure_frame_visible(self): logger.debug("scroll_root_element_: []".format( self._scroll_root_element)) original_fc = self.driver.frame_chain.clone() fc = self.driver.frame_chain.clone() self.driver.execute_script("window.scrollTo(0,0);") origin_driver = eyes_selenium_utils.get_underlying_driver(self.driver) while len(fc) > 0: logger.debug("fc count: {}".format(fc.size)) self.driver.switch_to.parent_frame_static(origin_driver.switch_to, fc) self.driver.execute_script("window.scrollTo(0,0);") prev_frame = fc.pop() frame = fc.peek scroll_root_element = None if fc.size == original_fc.size: logger.debug("PositionProvider: {}".format( self.position_provider)) self.position_provider.push_state() scroll_root_element = self._scroll_root_element else: if frame: scroll_root_element = frame.scroll_root_element if not scroll_root_element: scroll_root_element = self.driver.find_element_by_tag_name( "html") logger.debug("scroll_root_element {}".format(scroll_root_element)) position_provider = self._element_position_provider_from( scroll_root_element) position_provider.set_position(prev_frame.location) reg = Region.from_location_size(Point.zero(), prev_frame.inner_size) self._effective_viewport.intersect(reg) self.driver.switch_to.frames(original_fc) return original_fc
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("get_stitched_region()") logger.info("PositionProvider: %s ; Region: %s" % (position_provider, region)) with self.origin_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). with position_provider: logger.info("Getting top/left image...") image = self.image_provider.get_image() self.debug_screenshot_provider.save( image, self._debug_msg("original")) pixel_ratio = self._get_pixel_ratio(image) scaled_cut_provider = self.cut_provider.scale(pixel_ratio) image = self._cut_if_needed(image, scaled_cut_provider) region_in_screenshot = self._get_region_in_screenshot( region, image, pixel_ratio) image = self._crop_if_needed(image, region_in_screenshot) image = self._scale_if_needed(image, pixel_ratio) if full_area is None or full_area.is_empty: entire_size = self._get_entire_size( image, 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 (image.width >= entire_size.width and image.height >= entire_size.height): return image full_area = Region.from_location_size( Point.zero(), entire_size) image_parts = self._get_image_parts(full_area, image) stitched_image = self._create_stitched_image(full_area, image) # These will be used for storing the actual stitched size (it is # sometimes less than the size extracted via "get_entire_size"). last_successful_location = Point.zero() last_successful_part_size = RectangleSize.from_(image) # Take screenshot and stitch for each screenshot part logger.debug("Getting the rest of the image parts...") part_image = None for part_region in image_parts: logger.debug("Taking screenshot for %s" % part_region) # Scroll to the part's top/left origin_position = position_provider.set_position( part_region.location) target_position = origin_position.offset( -full_area.left, -full_area.top) logger.debug("Origin Position is set to %s" % origin_position) logger.debug("Target Position is %s" % target_position) # Actually taking the screenshot. logger.debug("Getting image...") part_image = self.image_provider.get_image() self.debug_screenshot_provider.save( part_image, self._debug_msg("original-scrolled-{}".format( position_provider.get_current_position())), ) part_image = self._cut_if_needed(part_image, scaled_cut_provider) part_image = self._crop_if_needed(part_image, region_in_screenshot) part_image = self._scale_if_needed(part_image, pixel_ratio) # Stitching the current part. stitched_image.paste(part_image, box=(target_position.x, target_position.y)) last_successful_location = origin_position if part_image: last_successful_part_size = RectangleSize.from_(part_image) logger.info("Stitching done!") # If the actual image size is smaller than the extracted size, we crop the image. stitched_image = self._crop_if_smaller( full_area, last_successful_location, last_successful_part_size, stitched_image, ) self.debug_screenshot_provider.save(stitched_image, self._debug_msg("stitched")) return stitched_image