def check_task_error(e): logger.debug("check_task_error: task.uuid: {}".format(check_task.uuid)) self.running_test.pending_exceptions.append(e) self.running_test.becomes_completed()
def set_viewport_size(driver, required_size): # type: (AnyWebDriver, ViewPort) -> None logger.debug("set_viewport_size({})".format(str(required_size))) actual_viewport_size = get_viewport_size(driver) if actual_viewport_size == required_size: logger.info("Required size already set.") return None try: # We move the window to (0,0) to have the best chance to be able to # set the viewport size as requested. driver.set_window_position(0, 0) except WebDriverException: logger.warning("Failed to move the browser window to (0,0)") set_browser_size_by_viewport_size(driver, actual_viewport_size, required_size) actual_viewport_size = get_viewport_size(driver) if actual_viewport_size == required_size: return None # Additional attempt. This Solves the "maximized browser" bug # (border size for maximized browser sometimes different than # non-maximized, so the original browser size calculation is # wrong). logger.info("Trying workaround for maximization...") set_browser_size_by_viewport_size(driver, actual_viewport_size, required_size) actual_viewport_size = get_viewport_size(driver) logger.debug("Current viewport size: {}".format(actual_viewport_size)) if actual_viewport_size == required_size: return None width_diff = abs(actual_viewport_size["width"] - required_size["width"]) width_step = -1 if width_diff > 0 else 1 # -1 for smaller size, 1 for larger height_diff = abs(actual_viewport_size["height"] - required_size["height"]) height_step = -1 if height_diff > 0 else 1 browser_size = get_window_size(driver) curr_width_change = 0 curr_height_change = 0 if width_diff <= _MAX_DIFF and height_diff <= _MAX_DIFF: logger.info("Trying workaround for zoom...") last_required_browser_size = None while (abs(curr_width_change) <= width_diff and abs(curr_height_change) <= height_diff): if abs(curr_width_change) <= width_diff: curr_width_change += width_step if abs(curr_height_change) <= height_diff: curr_height_change += height_step required_browser_size = dict( width=browser_size["width"] + curr_width_change, height=browser_size["height"] + curr_height_change, ) if required_browser_size == last_required_browser_size: logger.info( "Browser size is as required but viewport size does not match!" ) logger.info("Browser size: {}, Viewport size: {}".format( required_browser_size, actual_viewport_size)) logger.info("Stopping viewport size attempts.") break set_browser_size(driver, required_browser_size) last_required_browser_size = required_browser_size actual_viewport_size = get_viewport_size(driver) logger.info( "Current viewport size: {}".format(actual_viewport_size)) if actual_viewport_size == required_size: return None else: logger.info("Zoom workaround failed.") raise WebDriverException("Failed to set the viewport size.")
def render_task_error(e): logger.debug( "render_task_error: task.uuid: {}\n{}".format(render_task.uuid, str(e)) ) self.running_test.pending_exceptions.append(e) self.running_test.becomes_completed()
def check_task_error(e): logger.debug("check_task_error: task.uuid: {}".format(check_task.uuid)) self.pending_exceptions.append(e)
def _render_task( self, script_result, # type: Dict[Text, Any] tag, # type: Text visual_grid_manager, # type: VisualGridRunner region_selectors, # type: List region_to_check, # type: Region script_hooks, # type: Dict[Text, Any] check_settings, ): # type: (...)->RenderTask short_description = "{} of {}".format( self.configuration.test_name, self.configuration.app_name ) render_task = RenderTask( name="RunningTest.render {} - {}".format(short_description, tag), script=script_result, resource_cache=visual_grid_manager.resource_cache, put_cache=visual_grid_manager.put_cache, rendering_info=self.eyes.render_info(), eyes_connector=self.eyes, region_selectors=region_selectors, size_mode=check_settings.values.size_mode, region_to_check=region_to_check, script_hooks=script_hooks, agent_id=self.eyes.base_agent_id, selector=check_settings.values.selector, ) logger.debug("RunningTest %s" % render_task.name) render_index = render_task.add_running_test(self) def render_task_succeeded(render_statuses): # type: (List[RenderStatusResults]) -> None logger.debug( "render_task_succeeded: task.uuid: {}".format(render_task.uuid) ) logger.debug( "render_task_succeeded: task.uuid: {}".format(render_task.uuid) ) render_status = render_statuses[render_index] if render_status: if not render_status.device_size: render_status.device_size = self.browser_info.viewport_size self.eyes.render_status_for_task(render_task.uuid, render_status) if render_status.status == RenderStatus.RENDERED: for vgr in render_status.selector_regions: if vgr.error: logger.error(vgr.error) else: self.regions[render_task].append(vgr.to_region()) self.watch_render[render_task] = True if self.all_tasks_completed(self.watch_render): self.becomes_rendered() elif render_status and render_status.status == RenderStatus.ERROR: self.watch_render[render_task] = True del self.task_queue[:] del self.open_queue[:] del self.close_queue[:] self.watch_open = {} self.watch_task = {} self.watch_close = {} self.abort() if self.all_tasks_completed(self.watch_render): self.becomes_tested() else: logger.error( "Wrong render status! Render returned status {}".format( render_status ) ) self.becomes_completed() def render_task_error(e): logger.debug( "render_task_error: task.uuid: {}\n{}".format(render_task.uuid, str(e)) ) self.pending_exceptions.append(e) self.becomes_completed() render_task.on_task_succeeded(render_task_succeeded) render_task.on_task_error(render_task_error) self.render_queue.append(render_task) self.watch_render[render_task] = False return render_task
def abort_task_completed(): # type: () -> None logger.debug("abort_task_completed: task.uuid: {}".format(abort_task.uuid)) self.watch_close[abort_task] = True if self.all_tasks_completed(self.watch_close): self.becomes_completed()
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
def get_all_test_results(self, should_raise_exception=True): # type: (bool) -> TestResultsSummary logger.debug( "get_all_test_results({}) called".format(should_raise_exception)) return self._get_all_test_results_impl(should_raise_exception)
def aggregate_result(self, test, test_result): # type: (RunningTest, TestResults) -> None logger.debug( "aggregate_result({}, {}) called".format(test.test_uuid, test_result) ) self._all_test_results[test] = test_result
def close_task_succeeded(test_result): logger.debug("close_task_succeeded: task.uuid: {}".format( close_task.uuid)) self.test_result = test_result
def parse_frame_dom_resources(self, data): # noqa # type: (Dict) -> RGridDom logger.debug("parse_frame_dom_resources() call") base_url = data["url"] resource_urls = data.get("resourceUrls", []) all_blobs = data.get("blobs", []) frames = data.get("frames", []) discovered_resources_urls = set() discovered_resources_lock = Lock() def handle_resources(content_type, content, resource_url): logger.debug("handle_resources({0}, {1}) call".format( content_type, resource_url)) urls_from_css, urls_from_svg = [], [] if content_type.startswith("text/css"): urls_from_css = parsers.get_urls_from_css_resource(content) if content_type.startswith("image/svg"): urls_from_svg = parsers.get_urls_from_svg_resource(content) for discovered_url in urls_from_css + urls_from_svg: if discovered_url.startswith( "data:") or discovered_url.startswith("#"): # resource already in blob or not relevant continue target_url = apply_base_url(discovered_url, base_url, resource_url) with discovered_resources_lock: discovered_resources_urls.add(target_url) def get_resource(link): # type: (Text) -> VGResource logger.debug("get_resource({0}) call".format(link)) response = self.eyes_connector.download_resource(link) return VGResource.from_response(link, response, on_created=handle_resources) for f_data in frames: f_data["url"] = apply_base_url(f_data["url"], base_url) self.request_resources[f_data[ "url"]] = self.parse_frame_dom_resources(f_data).resource for blob in all_blobs: resource = VGResource.from_blob(blob, on_created=handle_resources) if resource.url.rstrip("#") == base_url: continue self.request_resources[resource.url] = resource for r_url in set(resource_urls).union(discovered_resources_urls): self.resource_cache.fetch_and_store(r_url, get_resource) self.resource_cache.process_all() # some discovered urls becomes available only after resources processed for r_url in discovered_resources_urls: self.resource_cache.fetch_and_store(r_url, get_resource) for r_url in set(resource_urls).union(discovered_resources_urls): val = self.resource_cache[r_url] if val is None: logger.debug("No response for {}".format(r_url)) continue self.request_resources[r_url] = self.resource_cache[r_url] return RGridDom(url=base_url, dom_nodes=data["cdt"], resources=self.request_resources)
def check_run(): logger.debug("check_run: render_task.uuid: {}".format( render_task.uuid)) self.eyes.check(tag, check_settings, render_task.uuid)
def open_task_error(e): logger.debug("render_task_error: task.uuid: {}\n{}".format( open_task.uuid, str(e))) self.pending_exceptions.append(e)
def clear(self): logger.debug("Clearing resource: {} {}".format(self.hash, self.url)) self.content = None
def open_task_error(e): logger.debug( "open_task_error: task.uuid: {}\n{}".format(open_task.uuid, str(e)) ) self.pending_exceptions.append(e) self.becomes_completed()
def open(self, eyes): # type: (VisualGridEyes) -> None self.all_eyes.append(eyes) logger.debug("VisualGridRunner.open(%s)" % eyes)
def abort_task_succeeded(test_result): logger.debug("abort_task_succeeded: task.uuid: {}".format(abort_task.uuid)) self.test_result = test_result if callable(self.on_results): self.on_results(test=self, test_result=test_result)
def open_task_succeeded(test_result): # type: (Optional[Any]) -> None logger.debug("open_task_succeeded: task.uuid: {}".format(open_task.uuid)) self.watch_open[open_task] = True if self.all_tasks_completed(self.watch_open): self.becomes_opened()
def abort_task_error(e): logger.debug( "abort_task_error: task.uuid: {}\n{}".format(abort_task.uuid, str(e)) ) self.pending_exceptions.append(e)
def get_resource(link): logger.debug("get_resource({0}) call".format(link)) matching_cookies = [c for c in cookies if is_cookie_for_url(c, link)] response = eyes_connector.download_resource(link, matching_cookies) return VGResource.from_response(link, response, find_child_resource_urls)