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.
- 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
|