eyes_selenium 2.39.1 → 3.0.6

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/applitools/capybara.rb +1 -1
  3. data/lib/applitools/selenium/border_aware_element_content_location_provider.rb +41 -0
  4. data/lib/applitools/selenium/browser.rb +1 -0
  5. data/lib/applitools/selenium/capybara/capybara_settings.rb +8 -0
  6. data/lib/applitools/selenium/capybara/driver.rb +1 -0
  7. data/lib/applitools/selenium/context_based_scale_provider.rb +36 -0
  8. data/lib/applitools/selenium/css_translate_position_provider.rb +66 -0
  9. data/lib/applitools/selenium/driver.rb +159 -44
  10. data/lib/applitools/selenium/element.rb +100 -8
  11. data/lib/applitools/selenium/element_position_provider.rb +48 -0
  12. data/lib/applitools/selenium/eyes.rb +922 -0
  13. data/lib/applitools/selenium/eyes_target_locator.rb +191 -0
  14. data/lib/applitools/selenium/eyes_web_driver_screenshot.rb +274 -0
  15. data/lib/applitools/selenium/frame.rb +24 -0
  16. data/lib/applitools/selenium/frame_chain.rb +68 -0
  17. data/lib/applitools/selenium/full_page_capture_algorithm.rb +162 -0
  18. data/lib/applitools/selenium/keyboard.rb +1 -0
  19. data/lib/applitools/selenium/match_window_task.rb +0 -197
  20. data/lib/applitools/selenium/mouse.rb +1 -0
  21. data/lib/applitools/selenium/move_to_region_visibility_strategy.rb +33 -0
  22. data/lib/applitools/selenium/nop_region_visibility_strategy.rb +16 -0
  23. data/lib/applitools/selenium/scroll_position_provider.rb +52 -0
  24. data/lib/applitools/selenium/takes_screenshot_image_provider.rb +36 -0
  25. data/lib/applitools/version.rb +1 -1
  26. data/lib/eyes_selenium.rb +19 -30
  27. metadata +24 -254
  28. data/.gitignore +0 -18
  29. data/.rspec +0 -2
  30. data/.rubocop.yml +0 -57
  31. data/.travis.yml +0 -17
  32. data/Gemfile +0 -4
  33. data/LICENSE.txt +0 -13
  34. data/README.md +0 -38
  35. data/Rakefile +0 -11
  36. data/certs/cacert.pem +0 -3557
  37. data/examples/appium_example_script.rb +0 -59
  38. data/examples/capybara_example.rb +0 -82
  39. data/examples/sauce_capybara_example.rb +0 -41
  40. data/examples/sauce_example.rb +0 -34
  41. data/examples/simple_test_script.rb +0 -23
  42. data/examples/watir_test_script.rb +0 -26
  43. data/eyes_selenium.gemspec +0 -89
  44. data/lib/applitools/appium_driver.rb +0 -7
  45. data/lib/applitools/base/batch_info.rb +0 -21
  46. data/lib/applitools/base/dimension.rb +0 -36
  47. data/lib/applitools/base/environment.rb +0 -19
  48. data/lib/applitools/base/image_position.rb +0 -10
  49. data/lib/applitools/base/mouse_trigger.rb +0 -33
  50. data/lib/applitools/base/point.rb +0 -34
  51. data/lib/applitools/base/region.rb +0 -112
  52. data/lib/applitools/base/server_connector.rb +0 -120
  53. data/lib/applitools/base/session.rb +0 -15
  54. data/lib/applitools/base/start_info.rb +0 -34
  55. data/lib/applitools/base/test_results.rb +0 -28
  56. data/lib/applitools/base/text_trigger.rb +0 -22
  57. data/lib/applitools/extensions.rb +0 -17
  58. data/lib/applitools/eyes.rb +0 -460
  59. data/lib/applitools/eyes_logger.rb +0 -38
  60. data/lib/applitools/method_tracer.rb +0 -22
  61. data/lib/applitools/poltergeist/applitools_compatible.rb +0 -28
  62. data/lib/applitools/poltergeist/driver.rb +0 -11
  63. data/lib/applitools/sauce.rb +0 -2
  64. data/lib/applitools/selenium/match_window_data.rb +0 -28
  65. data/lib/applitools/selenium_webdriver.rb +0 -8
  66. data/lib/applitools/utils/image_delta_compressor.rb +0 -148
  67. data/lib/applitools/utils/image_utils.rb +0 -143
  68. data/lib/applitools/utils/utils.rb +0 -49
  69. data/lib/applitools/watir_browser.rb +0 -8
  70. data/spec/driver_passthrough_spec.rb +0 -68
  71. data/spec/fixtures/static_test_file.html +0 -15
  72. data/spec/spec_helper.rb +0 -17
@@ -0,0 +1,191 @@
1
+ module Applitools::Selenium
2
+ class EyesTargetLocator < SimpleDelegator
3
+ extend Forwardable
4
+
5
+ def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
6
+
7
+ attr_reader :driver, :on_will_switch, :scroll_position_provider
8
+
9
+ def initialize(driver, original_target_locator, on_will_switch)
10
+ super(original_target_locator)
11
+ @driver = driver
12
+ @on_will_switch = on_will_switch
13
+ @scroll_position_provider = Applitools::Selenium::ScrollPositionProvider.new(driver)
14
+ end
15
+
16
+ # @param [Hash] options
17
+ # @option options [Fixnum] :index
18
+ # @option options [String] :name_or_id
19
+ # @option options [WebElement] :frameElement
20
+ # @return [Applitools::Selenium::Driver]
21
+ def frame(options = {})
22
+ raise Applitools::EyesIllegalArgument.new 'You must pass :index or :name_or_id or :frame_element option' unless
23
+ options[:index] || options[:name_or_id] || options[:frame_element]
24
+ if (needed_keys = (options.keys & %i(index name_or_id frame_element))).length == 1
25
+ send "frame_by_#{needed_keys.first}", options[needed_keys.first]
26
+ else
27
+ raise Applitools::EyesIllegalArgument.new 'You\'ve passed some extra keys!' /
28
+ 'Only :index, :name_or_id or :frame_elenent are allowed.'
29
+ end
30
+ end
31
+
32
+ def parent_frame
33
+ logger.info 'EyesTargetLocator.parent_frame()'
34
+ unless driver.frame_chain.empty?
35
+ on_will_switch.will_switch_to_frame :parent_frame, nil
36
+ logger.info 'Done! Switching to parent_frame...'
37
+ __getobj__.parent_frame
38
+ end
39
+ logger.info 'Done!'
40
+ driver
41
+ end
42
+
43
+ # @param [hash] options
44
+ # @option options [Applitools::Selenium::FrameChain] :frame_chain
45
+ # @option options [String] :frames_path
46
+ # @return Applitools::Selenium::Driver
47
+ def frames(options = {})
48
+ raise Applitools::EyesIllegalArgument.new 'You must pass :frame_chain or :frames_path' if
49
+ options[:frame_chain].nil? & options[:frames_path].nil?
50
+
51
+ if (needed_keys = (options.keys & %i(frame_chain frames_path))).length == 1
52
+ send "frames_by_#{needed_keys.first}", options[needed_keys.first]
53
+ else
54
+ raise Applitools::EyesIllegalArgument.new 'You\'ve passed some extra keys!' /
55
+ 'Only :frame_index or :frames_path are allowed.'
56
+ end
57
+ end
58
+
59
+ # A wrapper for the native method +default_content+
60
+ def default_content
61
+ logger.info 'EyesTargetLocator.default_content()'
62
+ unless driver.frame_chain.empty?
63
+ logger.info 'Making preparations...'
64
+ on_will_switch.will_switch_to_frame :default_content, nil
65
+ logger.info 'Done! Switching to default content...'
66
+ __getobj__.default_content
67
+ logger.info 'Done!'
68
+ end
69
+ driver
70
+ end
71
+
72
+ # A wrapper for the native method +window+
73
+ def window(name_or_handle)
74
+ logger.info 'EyesTargetLocator.window()'
75
+ logger.info 'Making preparaions...'
76
+ on_will_switch.will_switch_to_window name_or_handle
77
+ logger.info 'Done! Switching to window..'
78
+ __getobj__.window name_or_handle
79
+ logger.info 'Done!'
80
+ driver
81
+ end
82
+
83
+ # A wrapper for the native method +active_element+
84
+ def active_element
85
+ logger.info 'EyesTargetLocator.active_element()'
86
+ logger.info 'Switching to element...'
87
+ element = __getobj__.active_element
88
+
89
+ unless element.is_a? Selenium::WebDriver::Element
90
+ raise Applitools::EyesError.new(
91
+ 'Not an Selenium::WebDriver::Element!'
92
+ )
93
+ end
94
+
95
+ result = Applitools::Selenium::Element.new driver, element
96
+
97
+ logger.info 'Done!'
98
+ result
99
+ end
100
+
101
+ # A wrapper for a native method +alert+
102
+ def alert
103
+ logger.info 'EyesTargetLocator.alert()'
104
+ logger.info 'Switching to alert...'
105
+ result = __getobj__.alert
106
+ logger.info 'Done!'
107
+ result
108
+ end
109
+
110
+ private
111
+
112
+ def frame_by_index(index)
113
+ raise Applitools::EyesInvalidArgument.new 'You should pass Integer as :index value!' unless index.is_a? Integer
114
+ logger.info "EyesTargetLocator.frame(#{index})"
115
+ logger.info 'Getting frames list...'
116
+ frames = driver.find_elements(:css, 'frame, iframe')
117
+ raise Applitools::EyesNoSuchFrame.new "Frame index #{index} is invalid!" if index >= frames.size
118
+
119
+ logger.info 'Done! getting the specific frame...'
120
+ target_frame = frames[index]
121
+
122
+ logger.info 'Done! Making preparations...'
123
+ on_will_switch.will_switch_to_frame :frame, target_frame
124
+ logger.info 'Done! Switching to frame...'
125
+
126
+ # TODO: Looks like switching to frame by index (Fixnum) doesn't work at least for Chrome browser
127
+ # Is it better to use __getobj__.frame target_frame instead?
128
+ # __getobj__.frame index
129
+ __getobj__.frame target_frame
130
+
131
+ logger.info 'Done!'
132
+ driver
133
+ end
134
+
135
+ def frame_by_name_or_id(name_or_id)
136
+ logger.info "EyesTargetLocator.frame(#{name_or_id})"
137
+ # Finding the target element so we can report it.
138
+ # We use find elements(plural) to avoid exception when the element
139
+ # is not found.
140
+ logger.info 'Getting frames by name...'
141
+ frames = driver.find_elements :name, name_or_id
142
+ if frames.empty?
143
+ logger.info 'No frames found! Trying by id...'
144
+ frames = driver.find_elements :id, name_or_id
145
+ raise Applitools::EyesNoSuchFrame.new "No frame with name or id #{name_or_id} exists!" if frames.empty?
146
+ end
147
+ logger.info 'Done! Making preparations...'
148
+ on_will_switch.will_switch_to_frame(:frame, frames.first).last
149
+ logger.info 'Done! Switching to frame...'
150
+ __getobj__.frame frames.first
151
+
152
+ logger.info 'Done!'
153
+ driver
154
+ end
155
+
156
+ def frame_by_frame_element(web_element)
157
+ logger.info "EyesTargetLocator.frame(element) [#{web_element}]"
158
+ logger.info 'Done! Making preparations...'
159
+ on_will_switch.will_switch_to_frame :frame, web_element
160
+ logger.info 'Done! Switching to frame...'
161
+ __getobj__.frame web_element
162
+
163
+ logger.info 'Done!'
164
+ driver
165
+ end
166
+
167
+ def frames_by_frame_chain(frame_chain)
168
+ logger.info "EyesTargetLocator.frames(:frame_chain => a_chain) [#{frame_chain}]"
169
+ frame_chain.each do |frame|
170
+ logger.info 'Scrolling by parent scroll position...'
171
+ # scroll_position_provider.scroll_to frame.parent_scroll_position
172
+ logger.info 'Done! Switching to frame...'
173
+ frame(frame_element: frame.reference)
174
+ logger.info 'Done!'
175
+ logger.info 'Done switching into nested frames!'
176
+ driver
177
+ end
178
+ end
179
+
180
+ def frames_by_frames_path(frames_path)
181
+ logger.info 'EyesTargetLocator.frames(:frames_path => a_chain)'
182
+ frames_path.each do |frame_name_or_id|
183
+ logger.info 'Switching to frame...'
184
+ frame(name_or_id: frame_name_or_id)
185
+ logger.info 'Done!'
186
+ end
187
+ logger.info 'Done switching into nested frames!'
188
+ driver
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,274 @@
1
+ module Applitools::Selenium
2
+ # @!visibility private
3
+ class EyesWebDriverScreenshot < Applitools::EyesScreenshot
4
+ SCREENSHOT_TYPES = {
5
+ viewport: 'VIEPORT',
6
+ entire_frame: 'ENTIRE_FRAME'
7
+ }.freeze
8
+
9
+ INIT_CALLBACKS = {
10
+ [:driver, :screenshot_type, :frame_location_in_screenshot].sort => :initialize_main,
11
+ [:driver, :force_offset].sort => :initialize_main,
12
+ [:driver].sort => :initialize_main,
13
+ [:driver, :position_provider].sort => :initialize_main,
14
+ [:driver, :entire_frame_size].sort => :initialize_for_element,
15
+ [:driver, :entire_frame_size, :frame_location_in_screenshot].sort => :initialize_for_element
16
+ }.freeze
17
+
18
+ attr_accessor :driver
19
+ attr_accessor :frame_chain
20
+ private :frame_chain=
21
+
22
+ class << self
23
+ alias _new new
24
+
25
+ def new(*args)
26
+ image = args.shift
27
+ raise Applitools::EyesIllegalArgument.new 'image is expected to be Applitools::Screenshot!' unless
28
+ image.is_a? Applitools::Screenshot
29
+
30
+ options = args.first
31
+ if options.is_a? Hash
32
+ result = _new(image)
33
+ callback = INIT_CALLBACKS[options.keys.sort]
34
+ return result.tap { |o| o.send callback, options } if result.respond_to? callback
35
+ raise Applitools::EyesIllegalArgument.new 'Can\'t find an appropriate initializer!'
36
+ end
37
+ raise Applitools::EyesIllegalArgument.new "#{self.class}.initialize(): Hash is expected as an argument!"
38
+ end
39
+
40
+ def calc_frame_location_in_screenshot(frame_chain, screenshot_type, logger)
41
+ frame_chain = Applitools::Selenium::FrameChain.new other: frame_chain
42
+ logger.info 'Getting first frame...'
43
+ first_frame = frame_chain.shift
44
+ logger.info 'Done!'
45
+ location_in_screenshot = Applitools::Location.for first_frame.location
46
+
47
+ if screenshot_type == SCREENSHOT_TYPES[:viewport]
48
+ default_content_scroll = first_frame.parent_scroll_position
49
+ location_in_screenshot.offset_negative(
50
+ Applitools::Location.for(default_content_scroll.x, default_content_scroll.y)
51
+ )
52
+ end
53
+
54
+ logger.info 'Iterating over frames...'
55
+ frame_chain.each do |frame|
56
+ location_in_screenshot.offset(Applitools::Location.for(frame.location.x, frame.location.y))
57
+ .offset_negative(
58
+ Applitools::Location.for(
59
+ frame.parent_scroll_position.x, frame.parent_scroll_position.y
60
+ )
61
+ )
62
+ end
63
+ location_in_screenshot
64
+ end
65
+ end
66
+
67
+ def initialize_for_element(options = {})
68
+ Applitools::ArgumentGuard.not_nil options[:driver], 'options[:driver]'
69
+ Applitools::ArgumentGuard.not_nil options[:entire_frame_size], 'options[:entire_frame_size]'
70
+ entire_frame_size = options[:entire_frame_size]
71
+ self.driver = options[:driver]
72
+ self.frame_chain = driver.frame_chain
73
+ self.screenshot_type = SCREENSHOT_TYPES[:entire_frame]
74
+ self.scroll_position = Applitools::Location.new(0, 0)
75
+ self.scroll_position = Applitools::Location.new(0, 0).offset(options[:frame_location_in_screenshot]) if
76
+ options[:frame_location_in_screenshot].is_a? Applitools::Location
77
+ self.frame_location_in_screenshot = Applitools::Location.new(0, 0)
78
+ self.frame_window = Applitools::Region.new(0, 0, entire_frame_size.width, entire_frame_size.height)
79
+ end
80
+
81
+ def initialize_main(options = {})
82
+ # options = {screenshot_type: SCREENSHOT_TYPES[:viewport]}.merge options
83
+
84
+ Applitools::ArgumentGuard.hash options, 'options', [:driver]
85
+ Applitools::ArgumentGuard.not_nil options[:driver], 'options[:driver]'
86
+
87
+ self.driver = options[:driver]
88
+ self.position_provider = Applitools::Selenium::ScrollPositionProvider.new driver if
89
+ options[:position_provider].nil?
90
+
91
+ viewport_size = driver.default_content_viewport_size
92
+
93
+ self.frame_chain = driver.frame_chain
94
+ if !frame_chain.empty?
95
+ frame_size = frame_chain.current_frame_size
96
+ else
97
+ begin
98
+ frame_size = position_provider.entire_size
99
+ rescue
100
+ frame_size = viewport_size
101
+ end
102
+ end
103
+
104
+ begin
105
+ self.scroll_position = position_provider.current_position
106
+ rescue
107
+ self.scroll_position = Applitools::Location.new(0, 0)
108
+ end
109
+
110
+ if options[:screenshot_type].nil?
111
+ self.screenshot_type = if image.width <= viewport_size.width && image.height <= viewport_size.height
112
+ SCREENSHOT_TYPES[:viewport]
113
+ else
114
+ SCREENSHOT_TYPES[:entire_frame]
115
+ end
116
+ else
117
+ self.screenshot_type = options[:screenshot_type]
118
+ end
119
+
120
+ if options[:frame_location_in_screenshot].nil?
121
+ if !frame_chain.empty?
122
+ self.frame_location_in_screenshot = self.class.calc_frame_location_in_screenshot(
123
+ frame_chain, screenshot_type, logger
124
+ )
125
+ else
126
+ self.frame_location_in_screenshot = Applitools::Location.new(0, 0)
127
+ end
128
+ else
129
+ self.frame_location_in_screenshot = options[:frame_location_in_screenshot]
130
+ end
131
+
132
+ self.force_offset = Applitools::Location::TOP_LEFT
133
+ self.force_offset = options[:force_offset] if options[:force_offset]
134
+
135
+ logger.info 'Calculating frame window..'
136
+ self.frame_window = Applitools::Region.from_location_size(frame_location_in_screenshot, frame_size)
137
+ frame_window.intersect Applitools::Region.new(0, 0, image.width, image.height)
138
+
139
+ raise Applitools::EyesError.new 'Got empty frame window for screenshot!' if
140
+ frame_window.width <= 0 || frame_window.height <= 0
141
+
142
+ logger.info 'Done!'
143
+ end
144
+
145
+ # def scroll_position
146
+ # begin
147
+ # position_provider.state
148
+ # rescue
149
+ # Applitools::Location.new(0,0)
150
+ # end
151
+ # end
152
+
153
+ def convert_location(location, from, to)
154
+ Applitools::ArgumentGuard.not_nil location, 'location'
155
+ Applitools::ArgumentGuard.not_nil from, 'from'
156
+ Applitools::ArgumentGuard.not_nil to, 'to'
157
+
158
+ result = Applitools::Location.for location
159
+ return result if from == to
160
+ # if frame_chain.size.zero? && screenshot_type == SCREENSHOT_TYPES[:entire_frame]
161
+ # if (from == Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative] ||
162
+ # from == Applitools::EyesScreenshot::COORDINATE_TYPES[:context_as_is]) &&
163
+ # to == Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
164
+ # result.offset frame_location_in_screenshot
165
+ # elsif from == Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is] &&
166
+ # (to == Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative] ||
167
+ # to == Applitools::EyesScreenshot::COORDINATE_TYPES[:context_as_is])
168
+ # result.offset_negative frame_location_in_screenshot
169
+ # end
170
+ # end
171
+
172
+ case from
173
+ when Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
174
+ case to
175
+ when Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
176
+ result.offset_negative scroll_position
177
+ result.offset frame_location_in_screenshot
178
+ else
179
+ raise Applitools::EyesCoordinateTypeConversionException.new "Can't convert coordinates from #{from} to #{to}"
180
+ end
181
+ when Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
182
+ case to
183
+ when Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
184
+ result.offset_negative frame_location_in_screenshot
185
+ result.offset scroll_position
186
+ else
187
+ raise Applitools::EyesCoordinateTypeConversionException.new "Can't convert coordinates from #{from} to #{to}"
188
+ end
189
+ else
190
+ raise Applitools::EyesCoordinateTypeConversionException.new "Can't convert coordinates from #{from} to #{to}"
191
+ end
192
+
193
+ result
194
+ end
195
+
196
+ def frame_chain
197
+ Applitools::Selenium::FrameChain.new other: @frame_chain
198
+ end
199
+
200
+ def intersected_region(region, original_coordinate_types, result_coordinate_types)
201
+ return Applitools::Region::EMPTY if region.empty?
202
+ intersected_region = convert_region_location(
203
+ region, original_coordinate_types, Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
204
+ )
205
+ case original_coordinate_types
206
+ when Applitools::EyesScreenshot::COORDINATE_TYPES[:context_as_is]
207
+ nil
208
+ when Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
209
+ intersected_region.intersect frame_window
210
+ when Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
211
+ intersected_region.intersect Applitools::Region.new(0, 0, image.width, image.height)
212
+ else
213
+ raise Applitools::EyesCoordinateTypeConversionException.new(
214
+ "Unknown coordinates type: #{original_coordinate_types}"
215
+ )
216
+ end
217
+
218
+ return intersected_region if intersected_region.empty?
219
+ convert_region_location(
220
+ intersected_region,
221
+ Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is],
222
+ result_coordinate_types
223
+ )
224
+ end
225
+
226
+ def location_in_screenshot(location, coordinate_type)
227
+ location = convert_location(
228
+ location, coordinate_type, Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
229
+ )
230
+ unless frame_window.contains?(location.x, location.y)
231
+ raise Applitools::OutOfBoundsException.new(
232
+ "Location #{location} (#{coordinate_type}) is not visible in screenshot!"
233
+ )
234
+ end
235
+ location
236
+ end
237
+
238
+ def sub_screenshot(region, coordinate_type, throw_if_clipped = false)
239
+ logger.info "get_subscreenshot(#{region}, #{coordinate_type}, #{throw_if_clipped})"
240
+ Applitools::ArgumentGuard.not_nil region, 'region'
241
+ Applitools::ArgumentGuard.not_nil coordinate_type, 'coordinate_type'
242
+
243
+ region_to_check = Applitools::Region.from_location_size(
244
+ region.location.offset_negative(force_offset), region.size
245
+ )
246
+
247
+ as_is_subscreenshot_region = intersected_region region_to_check, coordinate_type,
248
+ Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
249
+
250
+ if as_is_subscreenshot_region.empty? || (throw_if_clipped && !as_is_subscreenshot_region.size == region.size)
251
+ raise Applitools::OutOfBoundsException.new "Region #{region} (#{coordinate_type}) is out" \
252
+ " of screenshot bounds [#{frame_window}]"
253
+ end
254
+
255
+ sub_screenshot_image = Applitools::Screenshot.new image.crop(as_is_subscreenshot_region.left,
256
+ as_is_subscreenshot_region.top, as_is_subscreenshot_region.width,
257
+ as_is_subscreenshot_region.height).to_datastream.to_blob
258
+
259
+ context_relative_region_location = convert_location as_is_subscreenshot_region.location,
260
+ Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is],
261
+ Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
262
+ result = self.class.new sub_screenshot_image, driver: driver,
263
+ entire_frame_size: Applitools::RectangleSize.new(sub_screenshot_image.width, sub_screenshot_image.height),
264
+ frame_location_in_screenshot: context_relative_region_location
265
+ logger.info 'Done!'
266
+ result
267
+ end
268
+
269
+ private
270
+
271
+ attr_accessor :position_provider, :scroll_position, :screenshot_type, :frame_location_in_screenshot,
272
+ :frame_window, :force_offset
273
+ end
274
+ end