class Applitools::Selenium::FullPageCaptureAlgorithm
@!visibility private
Constants
- MAX_SCROLL_BAR_SIZE
- MIN_SCREENSHOT_PART_HEIGHT
- MIN_SCREENSHOT_PART_WIDTH
Attributes
debug_screenshot_provider[R]
Public Class Methods
new(options = {})
click to toggle source
# File lib/applitools/selenium/full_page_capture_algorithm.rb, line 15 def initialize(options = {}) @debug_screenshot_provider = options[:debug_screenshot_provider] || Applitools::DebugScreenshotProvider.new.tag_access { '' }.debug_flag_access { false } end
Public Instance Methods
get_stitched_region(options = {})
click to toggle source
Returns the stitched image.
@param [Hash] options The options. @option [Applitools::Selenium::TakesScreenshotImageProvider] :image_provider @option [Applitools::Region] :region_to_check @option [Applitools::Selenium::ScrollPositionProvider] :origin_provider @option [Applitools::Selenium::ElementPositionProvider] :position_provider @option [Applitools::Selenium::ContextBasedScaleProvider] :scale_provider @option [Applitools::FixedCutProvider] :cut_provider @option [Integer] :wait_before_screenshots The time to wait before taking screenshot. @option [Faraday::Request::UrlEncoded] :eyes_screenshot_factory The images. @return [Applitools::Image] The entire image.
# File lib/applitools/selenium/full_page_capture_algorithm.rb, line 32 def get_stitched_region(options = {}) logger.info 'get_stitched_region() has been invoked.' image_provider = options[:image_provider] region_provider = options[:region_to_check] origin_provider = options[:origin_provider] position_provider = options[:position_provider] scale_provider = options[:scale_provider] cut_provider = options[:cut_provider] wait_before_screenshot = options[:wait_before_screenshots] eyes_screenshot_factory = options[:eyes_screenshot_factory] stitching_overlap = options[:stitching_overlap] || MAX_SCROLL_BAR_SIZE top_left_position = options[:top_left_position] || Applitools::Location::TOP_LEFT logger.info "Region to check: #{region_provider.region(false)}" logger.info "Coordinates type: #{region_provider.coordinate_type}" original_position = origin_provider.state current_position = nil set_position_retries = 3 while current_position.nil? || (current_position == top_left_position) && set_position_retries > 0 origin_provider.position = top_left_position sleep wait_before_screenshot current_position = origin_provider.current_position set_position_retries -= 1 end unless current_position == top_left_position origin_provider.restore_state original_position raise Applitools::EyesError.new 'Couldn\'t set position to the top/left corner!' end logger.info "Current position: #{current_position}" logger.info 'Getting top/left image...' image = image_provider.take_screenshot debug_screenshot_provider.save(image, 'left_top_original') image = scale_provider.scale_image(image) if scale_provider debug_screenshot_provider.save(image, 'left_top_original_scaled') image = cut_provider.cut(image) if cut_provider debug_screenshot_provider.save(image, 'left_top_original_cutted') logger.info 'Done! Creating screenshot object...' screenshot = eyes_screenshot_factory.call(image) begin entire_size = position_provider.entire_size(image.width, image.height) rescue Applitools::EyesDriverOperationException => e logger.error "Failed to extract entire size of region context: #{e.message}" logger.error "Using image size instead: #{image.width}x#{image.height}" entire_size = Applitools::RectangleSize.new image.width, image.height end if region_provider.region(false).size.square > 0 left_top_image = screenshot.sub_screenshot(region_provider.region(false), region_provider.coordinate_type).image else left_top_image = screenshot.image end debug_screenshot_provider.save_subscreenshot(left_top_image, region_provider.region(false)) image = left_top_image.image part_image_size = Applitools::RectangleSize.new( [image.width - stitching_overlap, MIN_SCREENSHOT_PART_WIDTH].max, [image.height - stitching_overlap, MIN_SCREENSHOT_PART_HEIGHT].max ) logger.info "Total size: #{entire_size}, image_part_size: #{part_image_size}" # Getting the list of sub-regions composing the whole region (we'll # take screenshot for each one). entire_page = Applitools::Region.from_location_size Applitools::Location::TOP_LEFT, entire_size # Notice that this might still happen even if we used # "getImagePart", since "entirePageSize" might be that of a frame. if image.width >= entire_size.width && image.height >= entire_size.height origin_provider.restore_state original_position return left_top_image end image_parts = entire_page.sub_regions(part_image_size) logger.info "Creating stitchedImage container. Size: #{entire_size}" stitched_image = ::ChunkyPNG::Image.new(entire_size.width, entire_size.height) logger.info 'Done! Adding initial screenshot..' logger.info "Initial part:(0,0) [#{image.width} x #{image.height}]" image.crop!( 0, 0, stitched_image.width < image.width ? stitched_image.width : image.width, stitched_image.height < image.height ? stitched_image.height : image.height ) stitched_image.replace! image, 0, 0 logger.info 'Done!' last_successful_location = Applitools::Location.new 0, 0 last_successful_part_size = Applitools::RectangleSize.new image.width, image.height original_stitched_state = position_provider.state stitched_image_region = Applitools::Region.new( 0, 0, stitched_image.width, stitched_image.height ) logger.info 'Getting the rest of the image parts...' # rubocop:disable Metrics/BlockLength image_parts.each_with_index do |part_regions, i| next unless i > 0 part_region = part_regions.first intersection = part_regions.last logger.info "Taking screenshot for #{part_region}" position_provider.position = part_region .location .offset(top_left_position) .offset_negative(intersection.location) sleep wait_before_screenshot current_position = position_provider.current_position logger.info "Set position to #{current_position}" logger.info 'Getting image...' part_image = image_provider.take_screenshot(debug_suffix: "scrolled_(#{current_position})") part_image = scale_provider.scale_image part_image if scale_provider debug_screenshot_provider.save(part_image, 'scaled') part_image = cut_provider.cut part_image if cut_provider debug_screenshot_provider.save(part_image, 'cutted') logger.info 'Done!' a_screenshot = eyes_screenshot_factory.call(part_image) if region_provider.region(false).size.square > 0 a_screenshot = a_screenshot.sub_screenshot( region_provider.region(false), Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative], false ) end position_to_replace = current_position.offset(intersection.location) replacement_region = Applitools::Region.new( position_to_replace.x, position_to_replace.y, a_screenshot.width - intersection.size.width, a_screenshot.height - intersection.size.height ) replacement_size = stitched_image_region.dup.intersect(replacement_region).size replacement_region_in_screenshot = Applitools::Region.from_location_size( Applitools::Location.from_any_attribute(intersection.location), replacement_size ) image_to_stitch = a_screenshot.sub_screenshot( replacement_region_in_screenshot, Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative], false ).image logger.info 'Stitching part into the image container...' stitched_image.replace! image_to_stitch, position_to_replace.x, position_to_replace.y logger.info 'Done!' last_successful_location = Applitools::Location.for position_to_replace.x, position_to_replace.y next unless image_to_stitch.area > 0 last_successful_part_size = Applitools::RectangleSize.new( image_to_stitch.width, image_to_stitch.height ) end # rubocop:enable Metrics/BlockLength logger.info 'Stitching done!' position_provider.restore_state original_stitched_state origin_provider.restore_state original_position actual_image_width = last_successful_location.x + last_successful_part_size.width actual_image_height = last_successful_location.y + last_successful_part_size.height logger.info "Extracted entire size: #{entire_size}" logger.info "Actual stitched size: #{stitched_image.width} x #{stitched_image.height}" logger.info "Calculated stitched size: #{actual_image_width} x #{actual_image_height}" if actual_image_width < stitched_image.width || actual_image_height < stitched_image.height logger.info 'Trimming unnecessary margins...' stitched_image.crop!(0, 0, [actual_image_width, stitched_image.width].min, [actual_image_height, stitched_image.height].min) debug_screenshot_provider.save(stitched_image, 'trimmed') logger.info 'Done!' end logger.info 'Converting to screenshot...' result_screenshot = Applitools::Screenshot.from_any_image(stitched_image) debug_screenshot_provider.save(result_screenshot, 'full_page') logger.info 'Done converting!' result_screenshot end