eyes_selenium 3.18.4 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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