eyes_selenium 3.18.2 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/applitools/selenium/browser_types.rb +10 -10
- data/lib/applitools/selenium/browsers_info.rb +8 -0
- data/lib/applitools/selenium/concerns/selenium_eyes.rb +2 -6
- data/lib/applitools/selenium/configuration.rb +1 -1
- data/lib/applitools/selenium/css_transform/css_transform.rb +2 -2
- data/lib/applitools/selenium/devices.rb +115 -24
- data/lib/applitools/selenium/driver.rb +20 -0
- data/lib/applitools/selenium/eyes.rb +2 -2
- data/lib/applitools/selenium/scripts/process_page_and_poll.rb +3 -4
- data/lib/applitools/selenium/scripts/templates.rb +1 -0
- data/lib/applitools/selenium/selenium_eyes.rb +52 -48
- data/lib/applitools/selenium/target.rb +119 -124
- data/lib/applitools/selenium/visual_grid/chrome_emulation_info.rb +4 -0
- data/lib/applitools/selenium/visual_grid/desktop_browser_info.rb +6 -0
- data/lib/applitools/selenium/visual_grid/dom_snapshot_script.rb +197 -0
- data/lib/applitools/selenium/visual_grid/ios_device_info.rb +12 -0
- data/lib/applitools/selenium/visual_grid/ios_device_name.rb +8 -0
- data/lib/applitools/selenium/visual_grid/render_task.rb +21 -2
- data/lib/applitools/selenium/visual_grid/thread_pool.rb +2 -1
- data/lib/applitools/selenium/visual_grid/visual_grid_eyes.rb +122 -77
- data/lib/applitools/selenium/visual_grid/visual_grid_runner.rb +4 -0
- data/lib/applitools/version.rb +2 -1
- data/lib/eyes_selenium.rb +9 -0
- metadata +11 -10
@@ -4,6 +4,7 @@ module Applitools
|
|
4
4
|
extend self
|
5
5
|
def get_script_by_file_name(fname)
|
6
6
|
script = nil
|
7
|
+
return script unless Dir.exist?(Applitools::JS_PATH)
|
7
8
|
begin
|
8
9
|
Dir.chdir(Applitools::JS_PATH) do
|
9
10
|
script = File.open(File.join('@applitools', 'dom-snapshot', 'dist', "#{fname}.js"), 'r').read
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
+
|
3
4
|
module Applitools::Selenium
|
4
5
|
# The main API gateway for the SDK
|
5
6
|
class SeleniumEyes < Applitools::EyesBase
|
@@ -56,16 +57,7 @@ module Applitools::Selenium
|
|
56
57
|
# @param [Applitools::Selenium::Driver] driver The driver instance.
|
57
58
|
# @param [Hash] viewport_size The required browser's viewport size.
|
58
59
|
def set_viewport_size(driver, viewport_size)
|
59
|
-
|
60
|
-
Applitools::ArgumentGuard.not_nil(viewport_size, 'viewport_size')
|
61
|
-
Applitools::ArgumentGuard.is_a?(viewport_size, 'viewport_size', Applitools::RectangleSize)
|
62
|
-
begin
|
63
|
-
Applitools::Utils::EyesSeleniumUtils.set_viewport_size eyes_driver(driver), viewport_size
|
64
|
-
rescue => e
|
65
|
-
Applitools::EyesLogger.error e.class
|
66
|
-
Applitools::EyesLogger.error e.message
|
67
|
-
raise Applitools::EyesError.new 'Failed to set viewport size!'
|
68
|
-
end
|
60
|
+
super
|
69
61
|
end
|
70
62
|
end
|
71
63
|
|
@@ -100,7 +92,7 @@ module Applitools::Selenium
|
|
100
92
|
:full_page_capture_algorithm_left_top_offset, :screenshot_type, :send_dom, :use_dom, :enable_patterns,
|
101
93
|
:utils,
|
102
94
|
:config
|
103
|
-
|
95
|
+
attr_accessor :driver
|
104
96
|
|
105
97
|
def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
|
106
98
|
def_delegators 'config', *Applitools::Selenium::Configuration.methods_to_delegate
|
@@ -116,7 +108,7 @@ module Applitools::Selenium
|
|
116
108
|
self.base_agent_id = "eyes.selenium.ruby/#{Applitools::VERSION}".freeze
|
117
109
|
self.check_frame_or_element = false
|
118
110
|
self.region_to_check = nil
|
119
|
-
self.force_full_page_screenshot = false
|
111
|
+
# self.force_full_page_screenshot = false
|
120
112
|
self.dont_get_title = false
|
121
113
|
self.device_pixel_ratio = UNKNOWN_DEVICE_PIXEL_RATIO
|
122
114
|
self.stitch_mode = Applitools::STITCH_MODE[:scroll]
|
@@ -162,41 +154,42 @@ module Applitools::Selenium
|
|
162
154
|
# @return [Applitools::Selenium::Driver] A wrapped web driver which enables Eyes
|
163
155
|
# trigger recording and frame handling
|
164
156
|
def open(options = {})
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
# Applitools::ArgumentGuard.
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
self.
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
end
|
199
|
-
|
157
|
+
universal_open(options)
|
158
|
+
# original_driver = options.delete(:driver)
|
159
|
+
# options[:viewport_size] = Applitools::RectangleSize.from_any_argument options[:viewport_size] if
|
160
|
+
# options[:viewport_size]
|
161
|
+
# Applitools::ArgumentGuard.not_nil original_driver, 'options[:driver]'
|
162
|
+
# # Applitools::ArgumentGuard.hash options, 'open(options)', [:app_name, :test_name]
|
163
|
+
#
|
164
|
+
# if disabled?
|
165
|
+
# logger.info('Ignored')
|
166
|
+
# return driver
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# @driver = self.class.eyes_driver(original_driver, self)
|
170
|
+
# perform_driver_specific_settings(original_driver)
|
171
|
+
#
|
172
|
+
# self.device_pixel_ratio = UNKNOWN_DEVICE_PIXEL_RATIO
|
173
|
+
# self.position_provider = self.class.position_provider(
|
174
|
+
# stitch_mode, driver, disable_horizontal_scrolling, disable_vertical_scrolling, explicit_entire_size
|
175
|
+
# )
|
176
|
+
#
|
177
|
+
# self.eyes_screenshot_factory = lambda do |image|
|
178
|
+
# Applitools::Selenium::ViewportScreenshot.new(
|
179
|
+
# image, driver: @driver, force_offset: position_provider.force_offset
|
180
|
+
# )
|
181
|
+
# end
|
182
|
+
#
|
183
|
+
# open_base(options) do
|
184
|
+
# self.viewport_size = get_viewport_size if force_driver_resolution_as_viewport_size
|
185
|
+
# ensure_running_session
|
186
|
+
# end
|
187
|
+
# if runner
|
188
|
+
# runner.add_batch(batch.id) do
|
189
|
+
# server_connector.close_batch(batch.id)
|
190
|
+
# end
|
191
|
+
# end
|
192
|
+
# @driver
|
200
193
|
end
|
201
194
|
|
202
195
|
def perform_driver_specific_settings(original_driver)
|
@@ -219,7 +212,15 @@ module Applitools::Selenium
|
|
219
212
|
# @!visibility private
|
220
213
|
def get_viewport_size(web_driver = driver)
|
221
214
|
Applitools::ArgumentGuard.not_nil 'web_driver', web_driver
|
222
|
-
self.utils.extract_viewport_size(driver)
|
215
|
+
# self.utils.extract_viewport_size(driver)
|
216
|
+
driver_config_json = web_driver.universal_driver_config
|
217
|
+
|
218
|
+
Applitools::EyesLogger.debug 'extract_viewport_size()'
|
219
|
+
viewport_size = runner.universal_client.core_get_viewport_size(driver_config_json)
|
220
|
+
result = Applitools::RectangleSize.new viewport_size[:width], viewport_size[:height]
|
221
|
+
|
222
|
+
Applitools::EyesLogger.debug "Viewport size is #{result}."
|
223
|
+
result
|
223
224
|
end
|
224
225
|
|
225
226
|
# Takes a snapshot and matches it with the expected output.
|
@@ -242,6 +243,9 @@ module Applitools::Selenium
|
|
242
243
|
logger.info "check(#{name}) is called"
|
243
244
|
self.tag_for_debug = name
|
244
245
|
Applitools::ArgumentGuard.is_a? target, 'target', Applitools::Selenium::Target
|
246
|
+
|
247
|
+
return universal_check(name, target)
|
248
|
+
|
245
249
|
target_to_check = target.finalize
|
246
250
|
original_overflow = nil
|
247
251
|
original_position_provider = position_provider
|
@@ -49,49 +49,10 @@ module Applitools
|
|
49
49
|
if args.empty?
|
50
50
|
reset_ignore
|
51
51
|
else
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
ignored_regions << case args.first
|
58
|
-
when Applitools::Region
|
59
|
-
proc { args.first.padding(requested_padding) }
|
60
|
-
when ::Selenium::WebDriver::Element
|
61
|
-
proc do |driver, return_element = false|
|
62
|
-
region = applitools_element_from_selenium_element(driver, args.first)
|
63
|
-
padding_proc = proc do |reg|
|
64
|
-
Applitools::Region.from_location_size(
|
65
|
-
reg.location, reg.size
|
66
|
-
).padding(requested_padding)
|
67
|
-
end
|
68
|
-
next region, padding_proc if return_element
|
69
|
-
padding_proc.call(region)
|
70
|
-
end
|
71
|
-
when Applitools::Selenium::Element
|
72
|
-
proc do |_driver, return_element = false|
|
73
|
-
region = args.first
|
74
|
-
padding_proc = proc do |reg|
|
75
|
-
Applitools::Region.from_location_size(
|
76
|
-
reg.location, reg.size
|
77
|
-
).padding(requested_padding)
|
78
|
-
end
|
79
|
-
next region, padding_proc if return_element
|
80
|
-
padding_proc.call(region)
|
81
|
-
end
|
82
|
-
else
|
83
|
-
proc do |driver, return_element = false|
|
84
|
-
region = driver.find_element(*args)
|
85
|
-
padding_proc = proc do |reg|
|
86
|
-
Applitools::Region.from_location_size(
|
87
|
-
reg.location, reg.size
|
88
|
-
).padding(requested_padding)
|
89
|
-
end
|
90
|
-
next region, padding_proc if return_element
|
91
|
-
padding_proc.call(region)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
52
|
+
value = convert_to_universal(args)
|
53
|
+
value = { type: args[0], selector: args[1] } if value.nil?
|
54
|
+
value = value[:selector] if value.is_a?(Hash) && (value[:type].to_s === 'id')
|
55
|
+
ignored_regions << value
|
95
56
|
end
|
96
57
|
self
|
97
58
|
end
|
@@ -120,49 +81,11 @@ module Applitools
|
|
120
81
|
# @!parse def floating(region_or_element, bounds, left,top, right, bottom, padding); end;
|
121
82
|
|
122
83
|
def floating(*args)
|
123
|
-
requested_padding =
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
value = case args.first
|
129
|
-
when Applitools::FloatingRegion
|
130
|
-
args.first.padding(requested_padding)
|
131
|
-
when ::Applitools::Region
|
132
|
-
Applitools::FloatingRegion.any(args.shift, *args).padding(requested_padding)
|
133
|
-
when ::Selenium::WebDriver::Element
|
134
|
-
proc do |driver, return_element = false|
|
135
|
-
args_dup = args.dup
|
136
|
-
region = applitools_element_from_selenium_element(driver, args_dup.shift)
|
137
|
-
padding_proc = proc do |reg|
|
138
|
-
Applitools::FloatingRegion.any(reg, *args_dup).padding(requested_padding)
|
139
|
-
end
|
140
|
-
next region, padding_proc if return_element
|
141
|
-
padding_proc.call(region)
|
142
|
-
end
|
143
|
-
when ::Applitools::Selenium::Element
|
144
|
-
proc do |_driver, return_element = false|
|
145
|
-
args_dup = args.dup
|
146
|
-
region = args_dup.shift
|
147
|
-
padding_proc = proc do |reg|
|
148
|
-
Applitools::FloatingRegion.any(reg, *args_dup).padding(requested_padding)
|
149
|
-
end
|
150
|
-
next region, padding_proc if return_element
|
151
|
-
padding_proc.call(region)
|
152
|
-
end
|
153
|
-
else
|
154
|
-
proc do |driver, return_element = false|
|
155
|
-
args_dup = args.dup
|
156
|
-
region = driver.find_element(args_dup.shift, args_dup.shift)
|
157
|
-
padding_proc = proc do |reg|
|
158
|
-
Applitools::FloatingRegion.any(
|
159
|
-
reg, *args_dup
|
160
|
-
).padding(requested_padding)
|
161
|
-
end
|
162
|
-
next region, padding_proc if return_element
|
163
|
-
padding_proc.call(region)
|
164
|
-
end
|
165
|
-
end
|
84
|
+
requested_padding = get_requested_padding(args)
|
85
|
+
value = convert_to_universal(args)
|
86
|
+
value = { type: args[0], selector: args[1] } if value.nil?
|
87
|
+
value = value[:selector] if value.is_a?(Hash) && (value[:type].to_s === 'id')
|
88
|
+
value = { region: value }.merge(requested_padding)
|
166
89
|
floating_regions << value
|
167
90
|
self
|
168
91
|
end
|
@@ -262,8 +185,9 @@ module Applitools
|
|
262
185
|
else
|
263
186
|
proc { |d| d.find_element(*args) }
|
264
187
|
end
|
265
|
-
frames <<
|
266
|
-
|
188
|
+
frames << element
|
189
|
+
# frames << frame_or_element if frame_or_element
|
190
|
+
# self.frame_or_element = element
|
267
191
|
reset_for_fullscreen
|
268
192
|
self
|
269
193
|
end
|
@@ -280,23 +204,10 @@ module Applitools
|
|
280
204
|
# @!parse def region(element, how, what); end;
|
281
205
|
|
282
206
|
def region(*args)
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
applitools_element_from_selenium_element(driver, args.first)
|
288
|
-
end
|
289
|
-
when Applitools::Selenium::Element, Applitools::Region
|
290
|
-
proc { args.first }
|
291
|
-
when String
|
292
|
-
proc do |driver|
|
293
|
-
driver.find_element(name_or_id: args.first)
|
294
|
-
end
|
295
|
-
else
|
296
|
-
proc do |driver|
|
297
|
-
driver.find_element(*args)
|
298
|
-
end
|
299
|
-
end
|
207
|
+
value = convert_to_universal(args)
|
208
|
+
value = { type: args[0], selector: args[1] } if value.nil?
|
209
|
+
value = value[:selector] if value.is_a?(Hash) && (value[:type].to_s === 'id')
|
210
|
+
self.region_to_check = value
|
300
211
|
self.coordinate_type = Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
|
301
212
|
options[:timeout] = nil
|
302
213
|
reset_ignore
|
@@ -315,11 +226,16 @@ module Applitools
|
|
315
226
|
end
|
316
227
|
|
317
228
|
def before_render_screenshot_hook(hook)
|
318
|
-
|
229
|
+
if hook.is_a?(Hash) && hook[:beforeCaptureScreenshot]
|
230
|
+
options[:script_hooks] = hook
|
231
|
+
else
|
232
|
+
options[:script_hooks][:beforeCaptureScreenshot] = hook
|
233
|
+
end
|
319
234
|
self
|
320
235
|
end
|
321
236
|
|
322
237
|
alias script_hook before_render_screenshot_hook
|
238
|
+
alias hooks before_render_screenshot_hook
|
323
239
|
|
324
240
|
def finalize
|
325
241
|
return self unless frame_or_element
|
@@ -339,11 +255,7 @@ module Applitools
|
|
339
255
|
"The region type should be one of [#{Applitools::AccessibilityRegionType.enum_values.join(', ')}]"
|
340
256
|
end
|
341
257
|
handle_frames
|
342
|
-
padding_proc = proc
|
343
|
-
Applitools::AccessibilityRegion.new(
|
344
|
-
region, options[:type]
|
345
|
-
)
|
346
|
-
end
|
258
|
+
padding_proc = proc { |region| Applitools::AccessibilityRegion.new(region, options[:type]) }
|
347
259
|
|
348
260
|
accessibility_regions << case args.first
|
349
261
|
when ::Selenium::WebDriver::Element
|
@@ -367,30 +279,34 @@ module Applitools
|
|
367
279
|
next element, padding_proc if return_element
|
368
280
|
padding_proc.call(element)
|
369
281
|
end
|
282
|
+
when :css
|
283
|
+
# (:css, '.ignore', type: 'LargeText')
|
284
|
+
{ region: args[1], type: options[:type] }
|
370
285
|
else
|
371
286
|
proc do |driver, return_element = false|
|
372
287
|
elements = driver.find_elements(*args)
|
373
288
|
next elements, padding_proc if return_element
|
374
289
|
elements.map { |e| padding_proc.call(e) }
|
375
290
|
end
|
291
|
+
|
376
292
|
end
|
377
293
|
self
|
378
294
|
end
|
379
295
|
|
380
296
|
def default_full_page_for_vg
|
381
|
-
if options[:stitch_content].nil?
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
end
|
297
|
+
# if options[:stitch_content].nil?
|
298
|
+
# case region_to_check
|
299
|
+
# when nil
|
300
|
+
# fully(true)
|
301
|
+
# when Proc
|
302
|
+
# begin
|
303
|
+
# r = region_to_check.call
|
304
|
+
# # fully(true) if r == Applitools::Region::EMPTY
|
305
|
+
# rescue StandardError
|
306
|
+
# fully(false)
|
307
|
+
# end
|
308
|
+
# end
|
309
|
+
# end
|
394
310
|
nil
|
395
311
|
end
|
396
312
|
|
@@ -398,6 +314,24 @@ module Applitools
|
|
398
314
|
self.convert_coordinates_block = block
|
399
315
|
end
|
400
316
|
|
317
|
+
def scroll_root_element(by, what = nil)
|
318
|
+
options[:scroll_root_element] = if is_element?(by)
|
319
|
+
ref = by.ref
|
320
|
+
ref = by.ref[1] if ref.is_a?(Array) && ref[0] === :element
|
321
|
+
{ elementId: ref }
|
322
|
+
elsif what
|
323
|
+
{ type: by.to_s, selector: what }
|
324
|
+
else
|
325
|
+
by
|
326
|
+
end
|
327
|
+
self
|
328
|
+
end
|
329
|
+
|
330
|
+
def layout_breakpoints(value = true)
|
331
|
+
options[:layout_breakpoints] = value.is_a?(Array) ? value : value
|
332
|
+
self
|
333
|
+
end
|
334
|
+
|
401
335
|
private
|
402
336
|
|
403
337
|
def reset_for_fullscreen
|
@@ -448,6 +382,67 @@ module Applitools
|
|
448
382
|
xpath = driver.execute_script(Applitools::Selenium::Scripts::GET_ELEMENT_XPATH_JS, selenium_element)
|
449
383
|
driver.find_element(:xpath, xpath)
|
450
384
|
end
|
385
|
+
|
386
|
+
def get_requested_padding(args)
|
387
|
+
if args.last.is_a? Applitools::PaddingBounds
|
388
|
+
args.pop
|
389
|
+
elsif args.last.is_a?(Applitools::FloatingBounds)
|
390
|
+
args.pop.to_hash
|
391
|
+
else
|
392
|
+
{}
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
|
397
|
+
|
398
|
+
def is_element?(el)
|
399
|
+
el.is_a?(::Selenium::WebDriver::Element) || (el.is_a?(Applitools::Selenium::Element) && el.respond_to?(:ref))
|
400
|
+
end
|
401
|
+
|
402
|
+
def is_region?(region)
|
403
|
+
region.is_a?(Applitools::FloatingRegion) || region.is_a?(Applitools::Region) # || region.is_a?(Applitools::Selenium::Element)
|
404
|
+
end
|
405
|
+
|
406
|
+
def is_finder?(finders)
|
407
|
+
return false unless finders.is_a?(Array)
|
408
|
+
return false unless finders[1]
|
409
|
+
return true if [:uiautomator, :predicate, :accessibility_id].include?(finders[0].to_sym)
|
410
|
+
Applitools::Selenium::Driver::FINDERS.has_key?(finders[0].to_sym)
|
411
|
+
end
|
412
|
+
|
413
|
+
def convert_to_universal(args)
|
414
|
+
if is_element?(args.first)
|
415
|
+
ref = args.first.ref
|
416
|
+
ref = args.first.ref[1] if ref.is_a?(Array) && ref[0] === :element
|
417
|
+
return { elementId: ref }
|
418
|
+
end
|
419
|
+
return args.first.to_hash if is_region?(args.first)
|
420
|
+
if is_finder?(args)
|
421
|
+
if Applitools::Selenium::Driver::FINDERS.has_key?(args[0])
|
422
|
+
return {type: Applitools::Selenium::Driver::FINDERS[args[0]], selector: args[1]}
|
423
|
+
end
|
424
|
+
case args[0]
|
425
|
+
when :uiautomator # ANDROID_UI_AUTOMATOR: '-android uiautomator'
|
426
|
+
return {type: '-android uiautomator', selector: args[1]}
|
427
|
+
when :predicate # IOS_PREDICATE: '-ios predicate string',
|
428
|
+
return {type: '-ios predicate string', selector: args[1]}
|
429
|
+
when :accessibility_id
|
430
|
+
return {type: 'accessibility id', selector: args[1]}
|
431
|
+
end
|
432
|
+
end
|
433
|
+
if args.first.is_a?(String)
|
434
|
+
return proc { |driver| driver.find_element(name_or_id: args.first) }
|
435
|
+
end
|
436
|
+
if args.first.is_a?(Hash) && args.first.has_key?('selector')
|
437
|
+
if args.first.has_key?('shadow')
|
438
|
+
return {selector: args.first['selector'], shadow: args.first['shadow']}
|
439
|
+
else
|
440
|
+
return {selector: args.first['selector']}
|
441
|
+
end
|
442
|
+
end
|
443
|
+
nil
|
444
|
+
end
|
445
|
+
|
451
446
|
end
|
452
447
|
end
|
453
448
|
end
|