eyes_selenium 3.14.3 → 3.14.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/lib/applitools/selenium/border_aware_element_content_location_provider.rb +2 -0
- data/lib/applitools/selenium/browser.rb +66 -56
- data/lib/applitools/selenium/context_based_scale_provider.rb +2 -0
- data/lib/applitools/selenium/css_transform/css_transform.rb +21 -0
- data/lib/applitools/selenium/css_translate_element_position_provider.rb +48 -0
- data/lib/applitools/selenium/css_translate_position_provider.rb +29 -10
- data/lib/applitools/selenium/dom_capture/dom_capture.rb +113 -0
- data/lib/applitools/selenium/dom_capture/dom_capture_script.rb +103 -0
- data/lib/applitools/selenium/driver.rb +9 -2
- data/lib/applitools/selenium/element.rb +2 -0
- data/lib/applitools/selenium/element_position_provider.rb +3 -1
- data/lib/applitools/selenium/entire_element_screenshot.rb +20 -0
- data/lib/applitools/selenium/eyes.rb +203 -396
- data/lib/applitools/selenium/eyes_screenshot.rb +60 -0
- data/lib/applitools/selenium/eyes_target_locator.rb +12 -24
- data/lib/applitools/selenium/fixed_cut_provider.rb +48 -0
- data/lib/applitools/selenium/frame.rb +11 -1
- data/lib/applitools/selenium/frame_chain.rb +9 -1
- data/lib/applitools/selenium/full_page_capture_algorithm.rb +85 -50
- data/lib/applitools/selenium/fullpage_screenshot.rb +37 -0
- data/lib/applitools/selenium/keyboard.rb +2 -0
- data/lib/applitools/selenium/mouse.rb +2 -0
- data/lib/applitools/selenium/move_to_region_visibility_strategy.rb +2 -0
- data/lib/applitools/selenium/nop_region_visibility_strategy.rb +2 -0
- data/lib/applitools/selenium/region_provider.rb +91 -0
- data/lib/applitools/selenium/sauce/driver.rb +2 -0
- data/lib/applitools/selenium/scroll_position_provider.rb +13 -2
- data/lib/applitools/selenium/takes_screenshot_image_provider.rb +5 -3
- data/lib/applitools/selenium/target.rb +32 -6
- data/lib/applitools/selenium/viewport_screenshot.rb +46 -0
- data/lib/applitools/selenium/viewport_size.rb +2 -0
- data/lib/applitools/version.rb +3 -1
- data/lib/eyes_selenium.rb +4 -9
- metadata +16 -27
- data/lib/applitools/capybara.rb +0 -8
- data/lib/applitools/poltergeist/applitools_compatible.rb +0 -32
- data/lib/applitools/poltergeist/driver.rb +0 -11
- data/lib/applitools/selenium/capybara/capybara_settings.rb +0 -23
- data/lib/applitools/selenium/capybara/driver.rb +0 -37
- data/lib/applitools/selenium/eyes_full_page_screenshot.rb +0 -47
- data/lib/applitools/selenium/eyes_web_driver_screenshot.rb +0 -341
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Applitools
|
4
|
+
module Selenium
|
5
|
+
class EyesScreenshot < Applitools::EyesScreenshot
|
6
|
+
attr_accessor :driver, :region_provider
|
7
|
+
def_delegators '@driver', :frame_chain
|
8
|
+
|
9
|
+
def initialize(image, options = {})
|
10
|
+
super image
|
11
|
+
self.region_provider = options[:region_provider] if options[:region_provider]
|
12
|
+
Applitools::ArgumentGuard.is_a?(
|
13
|
+
region_provider,
|
14
|
+
'options[:region_provider]',
|
15
|
+
Applitools::Selenium::RegionProvider
|
16
|
+
)
|
17
|
+
self.driver = region_provider.driver
|
18
|
+
end
|
19
|
+
|
20
|
+
def convert_location(location, _from, _to)
|
21
|
+
location.offset_negative(top_left_location)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the location in the screenshot.
|
25
|
+
#
|
26
|
+
# @param [Applitools::Location] location The location.
|
27
|
+
# @param [Applitools::EyesScreenshot::COORDINATE_TYPES] coordinate_type The type of the coordinate.
|
28
|
+
# @return [Applitools::Location] The location instance in the screenshot.
|
29
|
+
def location_in_screenshot(location, coordinate_type)
|
30
|
+
raise Applitools::Selenium::UnsupportedCoordinateType, coordinate_type unless
|
31
|
+
coordinate_type == Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
|
32
|
+
|
33
|
+
location = convert_location(
|
34
|
+
location, coordinate_type, Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
|
35
|
+
)
|
36
|
+
|
37
|
+
unless image_region.contains?(location.x, location.y)
|
38
|
+
raise Applitools::OutOfBoundsException,
|
39
|
+
"Location #{location} (#{coordinate_type}) is not visible in screenshot!"
|
40
|
+
end
|
41
|
+
location
|
42
|
+
end
|
43
|
+
|
44
|
+
def intersected_region(region, original_coordinate_types, result_coordinate_types)
|
45
|
+
raise Applitools::Selenium::UnsupportedCoordinateType, original_coordinate_types unless
|
46
|
+
original_coordinate_types == Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
|
47
|
+
raise Applitools::Selenium::UnsupportedCoordinateType, result_coordinate_types unless
|
48
|
+
result_coordinate_types == Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
|
49
|
+
|
50
|
+
return Applitools::Region::EMPTY if region.empty?
|
51
|
+
|
52
|
+
intersected_region = convert_region_location(
|
53
|
+
region, original_coordinate_types, Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
|
54
|
+
)
|
55
|
+
|
56
|
+
intersected_region.intersect(image_region)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Applitools::Selenium
|
2
4
|
class EyesTargetLocator < SimpleDelegator
|
3
5
|
extend Forwardable
|
@@ -38,19 +40,11 @@ module Applitools::Selenium
|
|
38
40
|
end
|
39
41
|
when Applitools::Selenium::Element
|
40
42
|
frame_by_frame_element(value)
|
43
|
+
when String
|
44
|
+
frame_by_name_or_id(value)
|
41
45
|
else
|
42
|
-
raise Applitools::EyesError 'Unknown frame selector to switch!'
|
46
|
+
raise Applitools::EyesError, 'Unknown frame selector to switch!'
|
43
47
|
end
|
44
|
-
# require 'pry'
|
45
|
-
# binding.pry
|
46
|
-
# raise Applitools::EyesIllegalArgument.new 'You must pass :index or :name_or_id or :frame_element option' unless
|
47
|
-
# options[:index] || options[:name_or_id] || options[:frame_element]
|
48
|
-
# if (needed_keys = (options.keys & [:index, :name_or_id, :frame_element])).length == 1
|
49
|
-
# send "frame_by_#{needed_keys.first}", options[needed_keys.first]
|
50
|
-
# else
|
51
|
-
# raise Applitools::EyesIllegalArgument.new 'You\'ve passed some extra keys!' /
|
52
|
-
# 'Only :index, :name_or_id or :frame_elenent are allowed.'
|
53
|
-
# end
|
54
48
|
end
|
55
49
|
|
56
50
|
# Switches to parent frame.
|
@@ -105,7 +99,7 @@ module Applitools::Selenium
|
|
105
99
|
def window(name_or_handle)
|
106
100
|
logger.info 'EyesTargetLocator.window()'
|
107
101
|
logger.info 'Making preparaions...'
|
108
|
-
on_will_switch.will_switch_to_window name_or_handle
|
102
|
+
# on_will_switch.will_switch_to_window name_or_handle
|
109
103
|
logger.info 'Done! Switching to window..'
|
110
104
|
__getobj__.window name_or_handle
|
111
105
|
logger.info 'Done!'
|
@@ -170,20 +164,14 @@ module Applitools::Selenium
|
|
170
164
|
|
171
165
|
def frame_by_name_or_id(name_or_id)
|
172
166
|
logger.info "EyesTargetLocator.frame(#{name_or_id})"
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
frames = driver.find_elements :name, name_or_id
|
178
|
-
if frames.empty?
|
179
|
-
logger.info 'No frames found! Trying by id...'
|
180
|
-
frames = driver.find_elements :id, name_or_id
|
181
|
-
raise Applitools::EyesNoSuchFrame.new "No frame with name or id #{name_or_id} exists!" if frames.empty?
|
182
|
-
end
|
167
|
+
|
168
|
+
logger.info 'Getting frame by name or id...'
|
169
|
+
target_frame = driver.find_element(name_or_id: name_or_id)
|
170
|
+
|
183
171
|
logger.info 'Done! Making preparations...'
|
184
|
-
on_will_switch.will_switch_to_frame(:frame,
|
172
|
+
on_will_switch.will_switch_to_frame(:frame, target_frame)
|
185
173
|
logger.info 'Done! Switching to frame...'
|
186
|
-
__getobj__.frame
|
174
|
+
__getobj__.frame target_frame
|
187
175
|
|
188
176
|
logger.info 'Done!'
|
189
177
|
driver
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Applitools
|
4
|
+
module Selenium
|
5
|
+
class FixedCutProvider
|
6
|
+
class << self
|
7
|
+
def viewport(image, viewport_size, region_to_check)
|
8
|
+
return nil if image.square == viewport_size.square
|
9
|
+
current_scroll_position = region_to_check.scroll_position_provider.current_position
|
10
|
+
image_canvas = Applitools::Region.new(0, 0, image.width, image.height)
|
11
|
+
viewport_frame = image_canvas.dup.intersect(
|
12
|
+
Applitools::Region.from_location_size(
|
13
|
+
Applitools::Location.new(current_scroll_position.left, current_scroll_position.top),
|
14
|
+
viewport_size
|
15
|
+
)
|
16
|
+
)
|
17
|
+
new(
|
18
|
+
viewport_frame.left,
|
19
|
+
viewport_frame.top,
|
20
|
+
image_canvas.right - viewport_frame.right,
|
21
|
+
image_canvas.bottom - viewport_frame.bottom
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(left, header, right, footer)
|
27
|
+
Applitools::ArgumentGuard.is_a?(left, 'left', Integer)
|
28
|
+
Applitools::ArgumentGuard.is_a?(header, 'header', Integer)
|
29
|
+
Applitools::ArgumentGuard.is_a?(right, 'right', Integer)
|
30
|
+
Applitools::ArgumentGuard.is_a?(footer, 'footer', Integer)
|
31
|
+
self.left = left
|
32
|
+
self.header = header
|
33
|
+
self.right = right
|
34
|
+
self.footer = footer
|
35
|
+
end
|
36
|
+
|
37
|
+
def cut(image)
|
38
|
+
crop_width = image.width - left - right
|
39
|
+
crop_height = image.height - header - footer
|
40
|
+
image.crop!(left, header, crop_width, crop_height)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_accessor :left, :header, :right, :footer
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Applitools::Selenium
|
2
4
|
# @!visibility private
|
3
5
|
class Frame
|
@@ -8,7 +10,7 @@ module Applitools::Selenium
|
|
8
10
|
send("#{param}=", options[param])
|
9
11
|
end
|
10
12
|
|
11
|
-
raise 'options[:location] must be instance of Applitools::Base::
|
13
|
+
raise 'options[:location] must be instance of Applitools::Base::Location' unless
|
12
14
|
location.is_a? Applitools::Location
|
13
15
|
|
14
16
|
raise 'options[:parent_scroll_position] must be instance of Applitools::Location' unless
|
@@ -20,5 +22,13 @@ module Applitools::Selenium
|
|
20
22
|
return if reference.is_a? Applitools::Selenium::Element
|
21
23
|
raise 'options[:reference] must be instance of Applitools::Selenium::Element'
|
22
24
|
end
|
25
|
+
|
26
|
+
def dup
|
27
|
+
super.tap do |r|
|
28
|
+
r.location = location.dup
|
29
|
+
r.size = size.dup
|
30
|
+
r.parent_scroll_position = parent_scroll_position.dup
|
31
|
+
end
|
32
|
+
end
|
23
33
|
end
|
24
34
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Applitools::Selenium
|
2
4
|
# @!visibility private
|
3
5
|
class FrameChain
|
@@ -15,7 +17,7 @@ module Applitools::Selenium
|
|
15
17
|
|
16
18
|
def same_frame_chain?(other)
|
17
19
|
return false unless size == other.size
|
18
|
-
|
20
|
+
ids == other.ids
|
19
21
|
end
|
20
22
|
|
21
23
|
def push(frame)
|
@@ -71,5 +73,11 @@ module Applitools::Selenium
|
|
71
73
|
end
|
72
74
|
|
73
75
|
class NoFramesException < RuntimeError; end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
def ids
|
80
|
+
map { |i| i.reference.ref }
|
81
|
+
end
|
74
82
|
end
|
75
83
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Applitools::Selenium
|
2
4
|
# @!visibility private
|
3
5
|
class FullPageCaptureAlgorithm
|
@@ -8,6 +10,7 @@ module Applitools::Selenium
|
|
8
10
|
|
9
11
|
MAX_SCROLL_BAR_SIZE = 50
|
10
12
|
MIN_SCREENSHOT_PART_HEIGHT = 10
|
13
|
+
MIN_SCREENSHOT_PART_WIDTH = 10
|
11
14
|
|
12
15
|
def initialize(options = {})
|
13
16
|
@debug_screenshot_provider = options[:debug_screenshot_provider] ||
|
@@ -37,34 +40,28 @@ module Applitools::Selenium
|
|
37
40
|
wait_before_screenshot = options[:wait_before_screenshots]
|
38
41
|
eyes_screenshot_factory = options[:eyes_screenshot_factory]
|
39
42
|
stitching_overlap = options[:stitching_overlap] || MAX_SCROLL_BAR_SIZE
|
43
|
+
top_left_position = options[:top_left_position] || Applitools::Location::TOP_LEFT
|
40
44
|
|
41
|
-
logger.info "Region to check: #{region_provider.region}"
|
45
|
+
logger.info "Region to check: #{region_provider.region(false)}"
|
42
46
|
logger.info "Coordinates type: #{region_provider.coordinate_type}"
|
43
47
|
|
44
48
|
original_position = origin_provider.state
|
45
49
|
current_position = nil
|
46
50
|
set_position_retries = 3
|
47
51
|
while current_position.nil? ||
|
48
|
-
(current_position
|
49
|
-
origin_provider.position =
|
52
|
+
(current_position == top_left_position) && set_position_retries > 0
|
53
|
+
origin_provider.position = top_left_position
|
50
54
|
sleep wait_before_screenshot
|
51
55
|
current_position = origin_provider.current_position
|
52
56
|
set_position_retries -= 1
|
53
57
|
end
|
54
58
|
|
55
|
-
unless current_position
|
59
|
+
unless current_position == top_left_position
|
56
60
|
origin_provider.restore_state original_position
|
57
61
|
raise Applitools::EyesError.new 'Couldn\'t set position to the top/left corner!'
|
58
62
|
end
|
59
63
|
|
60
|
-
|
61
|
-
entire_size = position_provider.entire_size
|
62
|
-
logger.info "Entire size of region context: #{entire_size}"
|
63
|
-
rescue Applitools::EyesDriverOperationException => e
|
64
|
-
logger.error "Failed to extract entire size of region context: #{e.message}"
|
65
|
-
logger.error "Using image size instead: #{image.width}x#{image.height}"
|
66
|
-
entire_size = Applitools::RectangleSize.new image.width, image.height
|
67
|
-
end
|
64
|
+
logger.info "Current position: #{current_position}"
|
68
65
|
|
69
66
|
logger.info 'Getting top/left image...'
|
70
67
|
image = image_provider.take_screenshot
|
@@ -76,44 +73,45 @@ module Applitools::Selenium
|
|
76
73
|
logger.info 'Done! Creating screenshot object...'
|
77
74
|
screenshot = eyes_screenshot_factory.call(image)
|
78
75
|
|
79
|
-
|
80
|
-
|
81
|
-
|
76
|
+
begin
|
77
|
+
entire_size = position_provider.entire_size(image.width, image.height)
|
78
|
+
rescue Applitools::EyesDriverOperationException => e
|
79
|
+
logger.error "Failed to extract entire size of region context: #{e.message}"
|
80
|
+
logger.error "Using image size instead: #{image.width}x#{image.height}"
|
81
|
+
entire_size = Applitools::RectangleSize.new image.width, image.height
|
82
|
+
end
|
83
|
+
|
84
|
+
if region_provider.region(false).size.square > 0
|
85
|
+
left_top_image = screenshot.sub_screenshot(region_provider.region(false), region_provider.coordinate_type).image
|
82
86
|
else
|
83
|
-
left_top_image = screenshot.
|
84
|
-
Applitools::Region.from_location_size(Applitools::Location.new(0, 0), entire_size),
|
85
|
-
Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
|
86
|
-
)
|
87
|
-
debug_screenshot_provider.save_subscreenshot(
|
88
|
-
left_top_image,
|
89
|
-
Applitools::Region.from_location_size(Applitools::Location.new(0, 0), entire_size)
|
90
|
-
)
|
87
|
+
left_top_image = screenshot.image
|
91
88
|
end
|
89
|
+
debug_screenshot_provider.save_subscreenshot(left_top_image, region_provider.region(false))
|
92
90
|
|
93
91
|
image = left_top_image.image
|
94
92
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
if image.width >= entire_size.width && image.height >= entire_size.height
|
99
|
-
origin_provider.restore_state original_position
|
100
|
-
return image
|
101
|
-
end
|
102
|
-
|
103
|
-
part_image_size = Applitools::RectangleSize.new image.width,
|
93
|
+
part_image_size = Applitools::RectangleSize.new(
|
94
|
+
[image.width - stitching_overlap, MIN_SCREENSHOT_PART_WIDTH].max,
|
104
95
|
[image.height - stitching_overlap, MIN_SCREENSHOT_PART_HEIGHT].max
|
96
|
+
)
|
105
97
|
|
106
98
|
logger.info "Total size: #{entire_size}, image_part_size: #{part_image_size}"
|
107
99
|
|
108
100
|
# Getting the list of sub-regions composing the whole region (we'll
|
109
101
|
# take screenshot for each one).
|
110
102
|
entire_page = Applitools::Region.from_location_size Applitools::Location::TOP_LEFT, entire_size
|
103
|
+
|
104
|
+
# Notice that this might still happen even if we used
|
105
|
+
# "getImagePart", since "entirePageSize" might be that of a frame.
|
106
|
+
if image.width >= entire_size.width && image.height >= entire_size.height
|
107
|
+
origin_provider.restore_state original_position
|
108
|
+
return left_top_image
|
109
|
+
end
|
110
|
+
|
111
111
|
image_parts = entire_page.sub_regions(part_image_size)
|
112
112
|
|
113
113
|
logger.info "Creating stitchedImage container. Size: #{entire_size}"
|
114
114
|
|
115
|
-
# Notice stitched_image uses the same type of image as the screenshots.
|
116
|
-
# stitched_image = Applitools::Screenshot.from_region entire_size
|
117
115
|
stitched_image = ::ChunkyPNG::Image.new(entire_size.width, entire_size.height)
|
118
116
|
logger.info 'Done! Adding initial screenshot..'
|
119
117
|
logger.info "Initial part:(0,0) [#{image.width} x #{image.height}]"
|
@@ -126,13 +124,29 @@ module Applitools::Selenium
|
|
126
124
|
|
127
125
|
original_stitched_state = position_provider.state
|
128
126
|
|
127
|
+
stitched_image_region = Applitools::Region.new(
|
128
|
+
0,
|
129
|
+
0,
|
130
|
+
stitched_image.width,
|
131
|
+
stitched_image.height
|
132
|
+
)
|
133
|
+
|
129
134
|
logger.info 'Getting the rest of the image parts...'
|
130
135
|
|
131
|
-
|
136
|
+
# rubocop:disable Metrics/BlockLength
|
137
|
+
image_parts.each_with_index do |part_regions, i|
|
132
138
|
next unless i > 0
|
139
|
+
|
140
|
+
part_region = part_regions.first
|
141
|
+
intersection = part_regions.last
|
142
|
+
|
133
143
|
logger.info "Taking screenshot for #{part_region}"
|
134
144
|
|
135
|
-
position_provider.position = part_region
|
145
|
+
position_provider.position = part_region
|
146
|
+
.location
|
147
|
+
.offset(top_left_position)
|
148
|
+
.offset_negative(intersection.location)
|
149
|
+
|
136
150
|
sleep wait_before_screenshot
|
137
151
|
current_position = position_provider.current_position
|
138
152
|
logger.info "Set position to #{current_position}"
|
@@ -145,30 +159,51 @@ module Applitools::Selenium
|
|
145
159
|
debug_screenshot_provider.save(part_image, 'cutted')
|
146
160
|
|
147
161
|
logger.info 'Done!'
|
148
|
-
|
149
|
-
|
150
|
-
|
162
|
+
|
163
|
+
a_screenshot = eyes_screenshot_factory.call(part_image)
|
164
|
+
|
165
|
+
if region_provider.region(false).size.square > 0
|
166
|
+
a_screenshot = a_screenshot.sub_screenshot(
|
167
|
+
region_provider.region(false),
|
168
|
+
Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative],
|
169
|
+
false
|
151
170
|
)
|
152
|
-
a_screenshot = eyes_screenshot_factory.call(part_image).sub_screenshot(region_to_check,
|
153
|
-
Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative], false)
|
154
|
-
debug_screenshot_provider.save_subscreenshot(a_screenshot, region_to_check)
|
155
|
-
rescue Applitools::OutOfBoundsException => e
|
156
|
-
logger.error e.message
|
157
|
-
break
|
158
171
|
end
|
159
172
|
|
173
|
+
position_to_replace = current_position.offset(intersection.location)
|
174
|
+
|
175
|
+
replacement_region = Applitools::Region.new(
|
176
|
+
position_to_replace.x,
|
177
|
+
position_to_replace.y,
|
178
|
+
a_screenshot.width - intersection.size.width,
|
179
|
+
a_screenshot.height - intersection.size.height
|
180
|
+
)
|
181
|
+
|
182
|
+
replacement_size = stitched_image_region.dup.intersect(replacement_region).size
|
183
|
+
replacement_region_in_screenshot = Applitools::Region.from_location_size(
|
184
|
+
Applitools::Location.from_any_attribute(intersection.location),
|
185
|
+
replacement_size
|
186
|
+
)
|
187
|
+
|
188
|
+
image_to_stitch = a_screenshot.sub_screenshot(
|
189
|
+
replacement_region_in_screenshot,
|
190
|
+
Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative],
|
191
|
+
false
|
192
|
+
).image
|
193
|
+
|
160
194
|
logger.info 'Stitching part into the image container...'
|
161
195
|
|
162
|
-
stitched_image.replace!
|
196
|
+
stitched_image.replace! image_to_stitch, position_to_replace.x, position_to_replace.y
|
163
197
|
logger.info 'Done!'
|
164
198
|
|
165
|
-
last_successful_location = Applitools::Location.for
|
166
|
-
next unless
|
199
|
+
last_successful_location = Applitools::Location.for position_to_replace.x, position_to_replace.y
|
200
|
+
next unless image_to_stitch.area > 0
|
167
201
|
last_successful_part_size = Applitools::RectangleSize.new(
|
168
|
-
|
169
|
-
|
202
|
+
image_to_stitch.width,
|
203
|
+
image_to_stitch.height
|
170
204
|
)
|
171
205
|
end
|
206
|
+
# rubocop:enable Metrics/BlockLength
|
172
207
|
|
173
208
|
logger.info 'Stitching done!'
|
174
209
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'eyes_screenshot'
|
3
|
+
module Applitools::Selenium
|
4
|
+
class FullpageScreenshot < Applitools::Selenium::EyesScreenshot
|
5
|
+
def sub_screenshot(region, _coordinate_type, throw_if_clipped = false, force_nil_if_clipped = false)
|
6
|
+
logger.info "get_subscreenshot(#{region}, #{throw_if_clipped})"
|
7
|
+
Applitools::ArgumentGuard.not_nil region, 'region'
|
8
|
+
|
9
|
+
as_is_subscreenshot_region = region.intersect(image_region)
|
10
|
+
|
11
|
+
if as_is_subscreenshot_region.empty? || (throw_if_clipped && as_is_subscreenshot_region.size != region.size)
|
12
|
+
return nil if force_nil_if_clipped
|
13
|
+
raise Applitools::OutOfBoundsException.new "Region #{region} is out" \
|
14
|
+
' of screenshot bounds'
|
15
|
+
end
|
16
|
+
|
17
|
+
sub_screenshot_image = Applitools::Screenshot.from_image(
|
18
|
+
image.crop(
|
19
|
+
as_is_subscreenshot_region.left,
|
20
|
+
as_is_subscreenshot_region.top,
|
21
|
+
as_is_subscreenshot_region.width,
|
22
|
+
as_is_subscreenshot_region.height
|
23
|
+
)
|
24
|
+
)
|
25
|
+
|
26
|
+
result = self.class.new(sub_screenshot_image, region_provider: region_provider).tap do |s|
|
27
|
+
s.top_left_location = top_left_location.dup.offset(region.location)
|
28
|
+
end
|
29
|
+
logger.info 'Done!'
|
30
|
+
result
|
31
|
+
end
|
32
|
+
|
33
|
+
def top_left_location
|
34
|
+
@top_left_location ||= Applitools::Location::TOP_LEFT
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|