eyes_selenium 3.18.1 → 4.0.0

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.
@@ -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
- Applitools::ArgumentGuard.not_nil(driver, 'Driver')
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
- attr_reader :driver
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
- original_driver = options.delete(:driver)
166
- options[:viewport_size] = Applitools::RectangleSize.from_any_argument options[:viewport_size] if
167
- options[:viewport_size]
168
- Applitools::ArgumentGuard.not_nil original_driver, 'options[:driver]'
169
- # Applitools::ArgumentGuard.hash options, 'open(options)', [:app_name, :test_name]
170
-
171
- if disabled?
172
- logger.info('Ignored')
173
- return driver
174
- end
175
-
176
- @driver = self.class.eyes_driver(original_driver, self)
177
- perform_driver_specific_settings(original_driver)
178
-
179
- self.device_pixel_ratio = UNKNOWN_DEVICE_PIXEL_RATIO
180
- self.position_provider = self.class.position_provider(
181
- stitch_mode, driver, disable_horizontal_scrolling, disable_vertical_scrolling, explicit_entire_size
182
- )
183
-
184
- self.eyes_screenshot_factory = lambda do |image|
185
- Applitools::Selenium::ViewportScreenshot.new(
186
- image, driver: @driver, force_offset: position_provider.force_offset
187
- )
188
- end
189
-
190
- open_base(options) do
191
- self.viewport_size = get_viewport_size if force_driver_resolution_as_viewport_size
192
- ensure_running_session
193
- end
194
- if runner
195
- runner.add_batch(batch.id) do
196
- server_connector.close_batch(batch.id)
197
- end
198
- end
199
- @driver
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
@@ -263,6 +267,7 @@ module Applitools::Selenium
263
267
  begin
264
268
  match_data = Applitools::MatchWindowData.new(default_match_settings)
265
269
  match_data.tag = name
270
+ match_data.variation_group_id = target_to_check.options[:variation_group_id] if target_to_check.options[:variation_group_id]
266
271
  eyes_element = target_to_check.region_to_check.call(driver)
267
272
 
268
273
  unless force_full_page_screenshot
@@ -49,49 +49,10 @@ module Applitools
49
49
  if args.empty?
50
50
  reset_ignore
51
51
  else
52
- requested_padding = if args.last.is_a? Applitools::PaddingBounds
53
- args.pop
54
- else
55
- Applitools::PaddingBounds::PIXEL_PADDING
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 = if args.last.is_a? Applitools::PaddingBounds
124
- args.pop
125
- else
126
- Applitools::PaddingBounds::PIXEL_PADDING
127
- end
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
@@ -249,6 +172,12 @@ module Applitools
249
172
  self
250
173
  end
251
174
 
175
+ def variation_group_id(value)
176
+ Applitools::ArgumentGuard.not_nil(value, 'variation_group_id')
177
+ options[:variation_group_id] = value
178
+ self
179
+ end
180
+
252
181
  def frame(*args)
253
182
  element = case args.first
254
183
  when ::Selenium::WebDriver::Element, Applitools::Selenium::Element, String
@@ -256,8 +185,9 @@ module Applitools
256
185
  else
257
186
  proc { |d| d.find_element(*args) }
258
187
  end
259
- frames << frame_or_element if frame_or_element
260
- self.frame_or_element = element
188
+ frames << element
189
+ # frames << frame_or_element if frame_or_element
190
+ # self.frame_or_element = element
261
191
  reset_for_fullscreen
262
192
  self
263
193
  end
@@ -274,23 +204,10 @@ module Applitools
274
204
  # @!parse def region(element, how, what); end;
275
205
 
276
206
  def region(*args)
277
- handle_frames
278
- self.region_to_check = case args.first
279
- when ::Selenium::WebDriver::Element
280
- proc do |driver|
281
- applitools_element_from_selenium_element(driver, args.first)
282
- end
283
- when Applitools::Selenium::Element, Applitools::Region
284
- proc { args.first }
285
- when String
286
- proc do |driver|
287
- driver.find_element(name_or_id: args.first)
288
- end
289
- else
290
- proc do |driver|
291
- driver.find_element(*args)
292
- end
293
- 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
294
211
  self.coordinate_type = Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
295
212
  options[:timeout] = nil
296
213
  reset_ignore
@@ -309,11 +226,16 @@ module Applitools
309
226
  end
310
227
 
311
228
  def before_render_screenshot_hook(hook)
312
- options[:script_hooks][:beforeCaptureScreenshot] = hook
229
+ if hook.is_a?(Hash) && hook[:beforeCaptureScreenshot]
230
+ options[:script_hooks] = hook
231
+ else
232
+ options[:script_hooks][:beforeCaptureScreenshot] = hook
233
+ end
313
234
  self
314
235
  end
315
236
 
316
237
  alias script_hook before_render_screenshot_hook
238
+ alias hooks before_render_screenshot_hook
317
239
 
318
240
  def finalize
319
241
  return self unless frame_or_element
@@ -333,11 +255,7 @@ module Applitools
333
255
  "The region type should be one of [#{Applitools::AccessibilityRegionType.enum_values.join(', ')}]"
334
256
  end
335
257
  handle_frames
336
- padding_proc = proc do |region|
337
- Applitools::AccessibilityRegion.new(
338
- region, options[:type]
339
- )
340
- end
258
+ padding_proc = proc { |region| Applitools::AccessibilityRegion.new(region, options[:type]) }
341
259
 
342
260
  accessibility_regions << case args.first
343
261
  when ::Selenium::WebDriver::Element
@@ -361,30 +279,34 @@ module Applitools
361
279
  next element, padding_proc if return_element
362
280
  padding_proc.call(element)
363
281
  end
282
+ when :css
283
+ # (:css, '.ignore', type: 'LargeText')
284
+ { region: args[1], type: options[:type] }
364
285
  else
365
286
  proc do |driver, return_element = false|
366
287
  elements = driver.find_elements(*args)
367
288
  next elements, padding_proc if return_element
368
289
  elements.map { |e| padding_proc.call(e) }
369
290
  end
291
+
370
292
  end
371
293
  self
372
294
  end
373
295
 
374
296
  def default_full_page_for_vg
375
- if options[:stitch_content].nil?
376
- case region_to_check
377
- when nil
378
- fully(true)
379
- when Proc
380
- begin
381
- r = region_to_check.call
382
- fully(true) if r == Applitools::Region::EMPTY
383
- rescue StandardError
384
- fully(false)
385
- end
386
- end
387
- 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
388
310
  nil
389
311
  end
390
312
 
@@ -392,6 +314,24 @@ module Applitools
392
314
  self.convert_coordinates_block = block
393
315
  end
394
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
+
395
335
  private
396
336
 
397
337
  def reset_for_fullscreen
@@ -442,6 +382,67 @@ module Applitools
442
382
  xpath = driver.execute_script(Applitools::Selenium::Scripts::GET_ELEMENT_XPATH_JS, selenium_element)
443
383
  driver.find_element(:xpath, xpath)
444
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
+
445
446
  end
446
447
  end
447
448
  end
@@ -51,6 +51,10 @@ module Applitools
51
51
  emulation_info.device_name + ' (chrome emulation)'
52
52
  end
53
53
 
54
+ def to_hash
55
+ {chromeEmulationInfo: emulation_info.json_data}
56
+ end
57
+
54
58
 
55
59
  private
56
60
 
@@ -40,6 +40,12 @@ module Applitools
40
40
  'desktop'
41
41
  end
42
42
 
43
+ def to_hash
44
+ result = viewport_size.to_h
45
+ result[:name] = browser_type unless browser_type.nil?
46
+ result
47
+ end
48
+
43
49
  end
44
50
  end
45
51
  end