eyes_selenium 2.39.1 → 3.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/applitools/capybara.rb +1 -1
- data/lib/applitools/selenium/border_aware_element_content_location_provider.rb +41 -0
- data/lib/applitools/selenium/browser.rb +1 -0
- data/lib/applitools/selenium/capybara/capybara_settings.rb +8 -0
- data/lib/applitools/selenium/capybara/driver.rb +1 -0
- data/lib/applitools/selenium/context_based_scale_provider.rb +36 -0
- data/lib/applitools/selenium/css_translate_position_provider.rb +66 -0
- data/lib/applitools/selenium/driver.rb +159 -44
- data/lib/applitools/selenium/element.rb +100 -8
- data/lib/applitools/selenium/element_position_provider.rb +48 -0
- data/lib/applitools/selenium/eyes.rb +922 -0
- data/lib/applitools/selenium/eyes_target_locator.rb +191 -0
- data/lib/applitools/selenium/eyes_web_driver_screenshot.rb +274 -0
- data/lib/applitools/selenium/frame.rb +24 -0
- data/lib/applitools/selenium/frame_chain.rb +68 -0
- data/lib/applitools/selenium/full_page_capture_algorithm.rb +162 -0
- data/lib/applitools/selenium/keyboard.rb +1 -0
- data/lib/applitools/selenium/match_window_task.rb +0 -197
- data/lib/applitools/selenium/mouse.rb +1 -0
- data/lib/applitools/selenium/move_to_region_visibility_strategy.rb +33 -0
- data/lib/applitools/selenium/nop_region_visibility_strategy.rb +16 -0
- data/lib/applitools/selenium/scroll_position_provider.rb +52 -0
- data/lib/applitools/selenium/takes_screenshot_image_provider.rb +36 -0
- data/lib/applitools/version.rb +1 -1
- data/lib/eyes_selenium.rb +19 -30
- metadata +24 -254
- data/.gitignore +0 -18
- data/.rspec +0 -2
- data/.rubocop.yml +0 -57
- data/.travis.yml +0 -17
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -13
- data/README.md +0 -38
- data/Rakefile +0 -11
- data/certs/cacert.pem +0 -3557
- data/examples/appium_example_script.rb +0 -59
- data/examples/capybara_example.rb +0 -82
- data/examples/sauce_capybara_example.rb +0 -41
- data/examples/sauce_example.rb +0 -34
- data/examples/simple_test_script.rb +0 -23
- data/examples/watir_test_script.rb +0 -26
- data/eyes_selenium.gemspec +0 -89
- data/lib/applitools/appium_driver.rb +0 -7
- data/lib/applitools/base/batch_info.rb +0 -21
- data/lib/applitools/base/dimension.rb +0 -36
- data/lib/applitools/base/environment.rb +0 -19
- data/lib/applitools/base/image_position.rb +0 -10
- data/lib/applitools/base/mouse_trigger.rb +0 -33
- data/lib/applitools/base/point.rb +0 -34
- data/lib/applitools/base/region.rb +0 -112
- data/lib/applitools/base/server_connector.rb +0 -120
- data/lib/applitools/base/session.rb +0 -15
- data/lib/applitools/base/start_info.rb +0 -34
- data/lib/applitools/base/test_results.rb +0 -28
- data/lib/applitools/base/text_trigger.rb +0 -22
- data/lib/applitools/extensions.rb +0 -17
- data/lib/applitools/eyes.rb +0 -460
- data/lib/applitools/eyes_logger.rb +0 -38
- data/lib/applitools/method_tracer.rb +0 -22
- data/lib/applitools/poltergeist/applitools_compatible.rb +0 -28
- data/lib/applitools/poltergeist/driver.rb +0 -11
- data/lib/applitools/sauce.rb +0 -2
- data/lib/applitools/selenium/match_window_data.rb +0 -28
- data/lib/applitools/selenium_webdriver.rb +0 -8
- data/lib/applitools/utils/image_delta_compressor.rb +0 -148
- data/lib/applitools/utils/image_utils.rb +0 -143
- data/lib/applitools/utils/utils.rb +0 -49
- data/lib/applitools/watir_browser.rb +0 -8
- data/spec/driver_passthrough_spec.rb +0 -68
- data/spec/fixtures/static_test_file.html +0 -15
- 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
|