Beispiel #1
0
    def __init__(self, driver):
        """
        Ctor.

        :param driver: EyesWebDriver instance.
        """
        self.driver = driver
        self.states = []
        self.current_position = Point(0, 0)
Beispiel #2
0
 def calc_frame_location_in_screenshot(frame_chain, is_viewport_screenshot):
     """
     Returns:
         (Point) The frame location as it would be on the screenshot. Notice that this value
         might actually be OUTSIDE the screenshot (e.g, if this is a viewport screenshot and
         the frame is located outside the viewport). This is not an error. The value can also
         be negative.
     """
     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
Beispiel #3
0
 def reset_origin(self):
     self._origin_position_provider.push_state()
     self._origin_position_provider.set_position(Point(0, 0))
     current_scroll_position = self._origin_position_provider.get_current_position(
     )
     if current_scroll_position.x != 0 or current_scroll_position.y != 0:
         self._origin_position_provider.pop_state()
         raise EyesError(
             "Couldn't scroll to the top/left part of the screen!")
Beispiel #4
0
class CSSTranslatePositionProvider(object):
    _JS_TRANSFORM_KEYS = ["transform", "-webkit-transform"]

    def __init__(self, driver):
        self.driver = driver
        self.states = []
        self.current_position = Point(0, 0)

    def _execute_script(self, script):
        return self.driver.execute_script(script)

    def get_current_position(self):
        """
        Extracts the current scroll position from the browser.
        Returns:
            (Point) The scroll position
        """
        return self.current_position.clone()

    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 set_position(self, point):
        """
        Commands the browser to scroll to a given position using javascript.
        """
        translate_command = "translate(-{}px, -{}px)".format(point.x, point.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 = point.clone()

    def push_state(self):
        self.states.append(self._get_current_transform())

    def pop_state(self):
        self._set_transform(self.states.pop())
Beispiel #5
0
 def get_current_position(self):
     """
     Extracts the current scroll position from the browser.
     Returns:
         (Point) The scroll position
     """
     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)
Beispiel #6
0
    def get_sub_screenshot_by_region(self, region):
        """
        Returns:
            (EyesScreenshot) A screenshot object representing the given region part of the image.
        """
        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 = self._screenshot.get_subimage(sub_screenshot_region)
        return EyesScreenshot(
            self._driver,
            screenshot,
            is_viewport_screenshot=self._is_viewport_screenshot,
            frame_location_in_screenshot=sub_screenshot_frame_location)
    def __init__(self, driver, screenshot=None, screenshot64=None,
                 is_viewport_screenshot=None, frame_location_in_screenshot=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.

        Args:
            driver: EyesWebDriver instance which handles the session from which the screenshot
                    was retrieved.
            (Optional) screenshot: (PngImage) image instance. If screenshot64 is None,
                                    this variable must NOT be none.
            (Optional) screenshot64: (str) The base64 representation of a png image. If screenshot
                                     is None, this variable must NOT be none.
            (Optional) frame_location_in_screenshot: (Point) The location of the frame relative
                                                    to the top,left of the screenshot.
            (Optional) is_viewport_screenshot: (boolean) Whether the screenshot object represents a
                                                viewport screenshot or a full screenshot.
        """
        self._screenshot64 = screenshot64
        if screenshot:
            self._screenshot = screenshot
        elif screenshot64:
            self._screenshot = _image_utils.png_image_from_bytes(base64.b64decode(screenshot64))
        else:
            raise EyesError("both screenshot and screenshot64 are None!")
        self._driver = driver
        self._viewport_size = driver.get_default_content_viewport_size()

        self._frame_chain = driver.get_frame_chain()
        if self._frame_chain:
            chain_len = len(self._frame_chain)
            self._frame_size = self._frame_chain[chain_len - 1].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_scroll_position()
        except WebDriverException:
            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 = EyesScreenshot \
                    .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))
Beispiel #8
0
    def get_full_page_screenshot(self):
        logger.info('getting full page screenshot..')

        # Saving the current frame reference and moving to the outermost frame.
        original_frame = self.get_frame_chain()
        self.switch_to.default_content()

        self.reset_origin()

        entire_page_size = self.get_entire_page_size()

        # Starting with the screenshot at 0,0
        part64 = self.get_screenshot_as_base64()
        screenshot = _image_utils.png_image_from_bytes(
            base64.b64decode(part64))

        # IMPORTANT This is required! Since when calculating the screenshot parts for full size,
        # we use a screenshot size which is a bit smaller (see comment below).
        if (screenshot.width >= entire_page_size['width']) and \
                (screenshot.height >= entire_page_size['height']):
            self.restore_origin()
            self.switch_to.frames(original_frame)
            return screenshot

        #  We use a smaller size than the actual screenshot size in order to eliminate duplication
        #  of bottom scroll bars, as well as footer-like elements with fixed position.
        screenshot_part_size = {
            'width':
            screenshot.width,
            'height':
            max(screenshot.height - self._MAX_SCROLL_BAR_SIZE,
                self._MIN_SCREENSHOT_PART_HEIGHT)
        }

        logger.debug("Total size: {0}, Screenshot part size: {1}".format(
            entire_page_size, screenshot_part_size))

        entire_page = Region(0, 0, entire_page_size['width'],
                             entire_page_size['height'])
        screenshot_parts = entire_page.get_sub_regions(screenshot_part_size)

        # Starting with the screenshot we already captured at (0,0).
        stitched_image = screenshot

        self.save_position()

        for part in screenshot_parts:
            # Since we already took the screenshot for 0,0
            if part.left == 0 and part.top == 0:
                logger.debug('Skipping screenshot for 0,0 (already taken)')
                continue
            logger.debug("Taking screenshot for {0}".format(part))
            # Scroll to the part's top/left and give it time to stabilize.
            self.scroll_to(Point(part.left, part.top))
            time.sleep(0.1)
            # Since screen size might cause the scroll to reach only part of the way
            current_scroll_position = self.get_current_position()
            logger.debug("Scrolled To ({0},{1})".format(
                current_scroll_position.x, current_scroll_position.y))
            part64 = self.get_screenshot_as_base64()
            part_image = _image_utils.png_image_from_bytes(
                base64.b64decode(part64))
            stitched_image.paste(current_scroll_position.x,
                                 current_scroll_position.y,
                                 part_image.pixel_bytes)

        self.restore_position()
        self.restore_origin()
        self.switch_to.frames(original_frame)

        return stitched_image