eyes_selenium 3.18.4 → 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.
@@ -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
@@ -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
@@ -262,8 +185,9 @@ module Applitools
262
185
  else
263
186
  proc { |d| d.find_element(*args) }
264
187
  end
265
- frames << frame_or_element if frame_or_element
266
- self.frame_or_element = element
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
- handle_frames
284
- self.region_to_check = case args.first
285
- when ::Selenium::WebDriver::Element
286
- proc do |driver|
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
- 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
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 do |region|
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
- case region_to_check
383
- when nil
384
- fully(true)
385
- when Proc
386
- begin
387
- r = region_to_check.call
388
- fully(true) if r == Applitools::Region::EMPTY
389
- rescue StandardError
390
- fully(false)
391
- end
392
- end
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
@@ -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
@@ -36,6 +36,10 @@ module Applitools
36
36
  ios_device_info.device_name
37
37
  end
38
38
 
39
+ def to_hash
40
+ {iosDeviceInfo: ios_device_info.to_hash}
41
+ end
42
+
39
43
  private
40
44
 
41
45
  class EmulationInfo < EmulationBaseInfo
@@ -49,6 +53,14 @@ module Applitools
49
53
  version: 'latest'
50
54
  }
51
55
  end
56
+
57
+ def to_hash
58
+ {
59
+ deviceName: device_name,
60
+ screenOrientation: screen_orientation,
61
+ iosVersion: 'latest'
62
+ }
63
+ end
52
64
  end
53
65
  end
54
66
  end
@@ -1,5 +1,8 @@
1
1
  module IosDeviceName
2
2
  extend self
3
+ IPhone_13_Pro_Max = 'iPhone 13 Pro Max'
4
+ IPhone_13_Pro = 'iPhone 13 Pro'
5
+ IPhone_13 = 'iPhone 13'
3
6
  IPhone_12_Pro_Max = 'iPhone 12 Pro Max'
4
7
  IPhone_12_Pro = 'iPhone 12 Pro'
5
8
  IPhone_12 = 'iPhone 12'
@@ -14,10 +17,14 @@ module IosDeviceName
14
17
  IPhone_7 = 'iPhone 7'
15
18
  IPad_Pro_3 = 'iPad Pro (12.9-inch) (3rd generation)'
16
19
  IPad_7 = 'iPad (7th generation)'
20
+ IPad_9 = 'iPad (9th generation)'
17
21
  IPad_Air_2 = 'iPad Air (2nd generation)'
18
22
 
19
23
  def enum_values
20
24
  [
25
+ IPhone_13_Pro_Max,
26
+ IPhone_13_Pro,
27
+ IPhone_13,
21
28
  IPhone_12_Pro_Max,
22
29
  IPhone_12_Pro,
23
30
  IPhone_12,
@@ -32,6 +39,7 @@ module IosDeviceName
32
39
  IPhone_7,
33
40
  IPad_Pro_3,
34
41
  IPad_7,
42
+ IPad_9,
35
43
  IPad_Air_2
36
44
  ]
37
45
  end
@@ -58,7 +58,8 @@ module Applitools
58
58
  end
59
59
 
60
60
  def init_or_renew_threads
61
- (concurrency - @thread_group.list.count).times do
61
+ one_concurrency = 1 # Thread's moved to universal server
62
+ (one_concurrency - @thread_group.list.count).times do
62
63
  logger.debug 'starting new thread (task worker)'
63
64
  next_thread
64
65
  end