eyes_selenium 3.18.4 → 6.9.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.
Files changed (32) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1713 -0
  3. data/Rakefile +86 -0
  4. data/eyes_selenium.gemspec +33 -0
  5. data/lib/applitools/eyes_selenium/version.rb +8 -0
  6. data/lib/applitools/selenium/browser_types.rb +14 -10
  7. data/lib/applitools/selenium/browsers_info.rb +8 -0
  8. data/lib/applitools/selenium/concerns/selenium_eyes.rb +2 -6
  9. data/lib/applitools/selenium/configuration.rb +13 -4
  10. data/lib/applitools/selenium/device_name_generated.rb +207 -0
  11. data/lib/applitools/selenium/devices.rb +106 -40
  12. data/lib/applitools/selenium/driver.rb +21 -1
  13. data/lib/applitools/selenium/eyes.rb +2 -2
  14. data/lib/applitools/selenium/full_page_capture_algorithm.rb +1 -1
  15. data/lib/applitools/selenium/selenium_eyes.rb +61 -49
  16. data/lib/applitools/selenium/target.rb +259 -162
  17. data/lib/applitools/selenium/visual_grid/chrome_emulation_info.rb +4 -0
  18. data/lib/applitools/selenium/visual_grid/desktop_browser_info.rb +6 -0
  19. data/lib/applitools/selenium/visual_grid/dom_snapshot_script.rb +2 -1
  20. data/lib/applitools/selenium/visual_grid/ios_device_info.rb +12 -0
  21. data/lib/applitools/selenium/visual_grid/ios_device_name.rb +3 -35
  22. data/lib/applitools/selenium/visual_grid/ios_device_name_generated.rb +93 -0
  23. data/lib/applitools/selenium/visual_grid/running_test.rb +1 -1
  24. data/lib/applitools/selenium/visual_grid/thread_pool.rb +2 -1
  25. data/lib/applitools/selenium/visual_grid/vg_resource.rb +7 -6
  26. data/lib/applitools/selenium/visual_grid/visual_grid_eyes.rb +139 -55
  27. data/lib/applitools/selenium/visual_grid/visual_grid_runner.rb +6 -2
  28. data/lib/eyes_selenium.rb +23 -2
  29. metadata +14 -26
  30. data/lib/applitools/selenium/scripts/process_page_and_poll.rb +0 -17
  31. data/lib/applitools/selenium/scripts/templates.rb +0 -34
  32. data/lib/applitools/version.rb +0 -5
@@ -21,7 +21,7 @@ module Applitools
21
21
 
22
22
  attr_accessor :element, :frames, :region_to_check, :coordinate_type, :options, :ignored_regions,
23
23
  :floating_regions, :frame_or_element, :regions, :layout_regions, :content_regions,
24
- :strict_regions, :accessibility_regions, :convert_coordinates_block
24
+ :strict_regions, :accessibility_regions, :dynamic_regions, :convert_coordinates_block
25
25
 
26
26
  private :frame_or_element, :frame_or_element=
27
27
 
@@ -49,49 +49,8 @@ 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
+ region = region_from_args(args)
53
+ ignored_regions << region if region
95
54
  end
96
55
  self
97
56
  end
@@ -120,71 +79,36 @@ module Applitools
120
79
  # @!parse def floating(region_or_element, bounds, left,top, right, bottom, padding); end;
121
80
 
122
81
  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
166
- floating_regions << value
82
+ options = Applitools::Utils.extract_options!(args)
83
+ padding = options && options[:padding]
84
+ requested_padding = get_requested_padding(padding, args)
85
+ bounds = get_bounds(args)
86
+ value = convert_to_universal(args)
87
+ value = { type: args[0], selector: args[1] } if value.nil?
88
+ value = value[:selector] if value.is_a?(Hash) && (value[:type].to_s === 'id')
89
+ region = { region: value }
90
+ region.merge!(bounds) if bounds != {}
91
+ region.merge!(padding: requested_padding) if requested_padding != {}
92
+ region.merge!(regionId: options[:region_id]) if options[:region_id]
93
+ floating_regions << region
167
94
  self
168
95
  end
169
96
 
170
97
  def layout(*args)
171
- return match_level(Applitools::MatchLevel::LAYOUT) if args.empty?
172
- region = process_region(*args)
173
- layout_regions << region
98
+ region = region_from_args(args)
99
+ layout_regions << region if region
174
100
  self
175
101
  end
176
102
 
177
103
  def content(*args)
178
- return match_level(Applitools::MatchLevel::CONTENT) if args.empty?
179
- region = process_region(*args)
180
- content_regions << region
104
+ region = region_from_args(args)
105
+ content_regions << region if region
181
106
  self
182
107
  end
183
108
 
184
109
  def strict(*args)
185
- return match_level(Applitools::MatchLevel::STRICT) if args.empty?
186
- region = process_region(*args)
187
- strict_regions << region
110
+ region = region_from_args(args)
111
+ strict_regions << region if region
188
112
  self
189
113
  end
190
114
 
@@ -229,6 +153,8 @@ module Applitools
229
153
  replace_element(original_region, new_region, ignored_regions)
230
154
  when :accessibility_regions
231
155
  replace_element(original_region, new_region, accessibility_regions)
156
+ when :dynamic_regions
157
+ replace_element(original_region, new_region, dynamic_regions)
232
158
  end
233
159
  end
234
160
 
@@ -262,8 +188,9 @@ module Applitools
262
188
  else
263
189
  proc { |d| d.find_element(*args) }
264
190
  end
265
- frames << frame_or_element if frame_or_element
266
- self.frame_or_element = element
191
+ frames << element
192
+ # frames << frame_or_element if frame_or_element
193
+ # self.frame_or_element = element
267
194
  reset_for_fullscreen
268
195
  self
269
196
  end
@@ -280,23 +207,10 @@ module Applitools
280
207
  # @!parse def region(element, how, what); end;
281
208
 
282
209
  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
210
+ value = convert_to_universal(args)
211
+ value = { type: args[0], selector: args[1] } if value.nil?
212
+ value = value[:selector] if value.is_a?(Hash) && (value[:type].to_s === 'id')
213
+ self.region_to_check = value
300
214
  self.coordinate_type = Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
301
215
  options[:timeout] = nil
302
216
  reset_ignore
@@ -315,11 +229,16 @@ module Applitools
315
229
  end
316
230
 
317
231
  def before_render_screenshot_hook(hook)
318
- options[:script_hooks][:beforeCaptureScreenshot] = hook
232
+ if hook.is_a?(Hash) && hook[:beforeCaptureScreenshot]
233
+ options[:script_hooks] = hook
234
+ else
235
+ options[:script_hooks][:beforeCaptureScreenshot] = hook
236
+ end
319
237
  self
320
238
  end
321
239
 
322
240
  alias script_hook before_render_screenshot_hook
241
+ alias hooks before_render_screenshot_hook
323
242
 
324
243
  def finalize
325
244
  return self unless frame_or_element
@@ -339,58 +258,95 @@ module Applitools
339
258
  "The region type should be one of [#{Applitools::AccessibilityRegionType.enum_values.join(', ')}]"
340
259
  end
341
260
  handle_frames
342
- padding_proc = proc do |region|
343
- Applitools::AccessibilityRegion.new(
344
- region, options[:type]
345
- )
346
- end
261
+ padding_proc = proc { |region| Applitools::AccessibilityRegion.new(region, options[:type]) }
347
262
 
348
263
  accessibility_regions << case args.first
349
- when ::Selenium::WebDriver::Element
350
- proc do |driver, return_element = false|
351
- element = applitools_element_from_selenium_element(driver, args.first)
352
- next element, padding_proc if return_element
353
- padding_proc.call(element)
354
- end
355
- when Applitools::Selenium::Element
356
- proc do |_driver, return_element = false|
357
- next args.first, padding_proc if return_element
358
- padding_proc.call(args.first)
359
- end
360
- when Applitools::Region
361
- Applitools::AccessibilityRegion.new(
362
- args.first, options[:type]
363
- )
364
- when String
365
- proc do |driver, return_element = false|
366
- element = driver.find_element(name_or_id: args.first)
367
- next element, padding_proc if return_element
368
- padding_proc.call(element)
369
- end
370
- else
371
- proc do |driver, return_element = false|
372
- elements = driver.find_elements(*args)
373
- next elements, padding_proc if return_element
374
- elements.map { |e| padding_proc.call(e) }
375
- end
376
- end
264
+ when ::Selenium::WebDriver::Element
265
+ proc do |driver, return_element = false|
266
+ element = applitools_element_from_selenium_element(driver, args.first)
267
+ next element, padding_proc if return_element
268
+ padding_proc.call(element)
269
+ end
270
+ when Applitools::Selenium::Element
271
+ proc do |_driver, return_element = false|
272
+ next args.first, padding_proc if return_element
273
+ padding_proc.call(args.first)
274
+ end
275
+ when Applitools::Region
276
+ Applitools::AccessibilityRegion.new(
277
+ args.first, options[:type]
278
+ )
279
+ when String
280
+ proc do |driver, return_element = false|
281
+ element = driver.find_element(name_or_id: args.first)
282
+ next element, padding_proc if return_element
283
+ padding_proc.call(element)
284
+ end
285
+ when :css
286
+ { region: args[1], type: options[:type] }
287
+ else
288
+ proc do |driver, return_element = false|
289
+ elements = driver.find_elements(*args)
290
+ next elements, padding_proc if return_element
291
+ elements.map { |e| padding_proc.call(e) }
292
+ end
293
+ end
377
294
  self
378
295
  end
379
296
 
380
- 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)
297
+ def dynamic(*args)
298
+ options = Applitools::Utils.extract_options! args
299
+ handle_frames
300
+ padding_proc = proc { |region| Applitools::DynamicRegion.new(region, options[:type]) }
301
+
302
+ dynamic_regions << case args.first
303
+ when ::Selenium::WebDriver::Element
304
+ proc do |driver, return_element = false|
305
+ element = applitools_element_from_selenium_element(driver, args.first)
306
+ next element, padding_proc if return_element
307
+ padding_proc.call(element)
308
+ end
309
+ when Applitools::Selenium::Element
310
+ proc do |_driver, return_element = false|
311
+ next args.first, padding_proc if return_element
312
+ padding_proc.call(args.first)
313
+ end
314
+ when Applitools::Region
315
+ Applitools::DynamicRegion.new(
316
+ args.first, options[:type]
317
+ )
318
+ when String
319
+ proc do |driver, return_element = false|
320
+ element = driver.find_element(name_or_id: args.first)
321
+ next element, padding_proc if return_element
322
+ padding_proc.call(element)
323
+ end
324
+ when :css
325
+ { region: args[1], type: options[:type] }
326
+ else
327
+ proc do |driver, return_element = false|
328
+ elements = driver.find_elements(*args)
329
+ next elements, padding_proc if return_element
330
+ elements.map { |e| padding_proc.call(e) }
391
331
  end
392
332
  end
393
- end
333
+ self
334
+ end
335
+
336
+ def default_full_page_for_vg
337
+ # if options[:stitch_content].nil?
338
+ # case region_to_check
339
+ # when nil
340
+ # fully(true)
341
+ # when Proc
342
+ # begin
343
+ # r = region_to_check.call
344
+ # # fully(true) if r == Applitools::Region::EMPTY
345
+ # rescue StandardError
346
+ # fully(false)
347
+ # end
348
+ # end
349
+ # end
394
350
  nil
395
351
  end
396
352
 
@@ -398,6 +354,54 @@ module Applitools
398
354
  self.convert_coordinates_block = block
399
355
  end
400
356
 
357
+ def scroll_root_element(by, what = nil)
358
+ options[:scroll_root_element] = if is_element?(by)
359
+ ref = by.ref
360
+ ref = by.ref[1] if ref.is_a?(Array) && ref[0] === :element
361
+ { elementId: ref }
362
+ elsif what
363
+ { type: by.to_s, selector: what }
364
+ else
365
+ by
366
+ end
367
+ self
368
+ end
369
+
370
+ def layout_breakpoints(value = true, reload: nil, height_breakpoints: nil)
371
+ if value.is_a?(Hash) && (value.has_key?(:breakpoints) || value.has_key?('breakpoints'))
372
+ options[:layout_breakpoints] = value
373
+
374
+ # Set defaults for the new options if they're not in the hash
375
+ # Need to check both symbol and string keys
376
+ options[:layout_breakpoints][:reload] = value[:reload] || value['reload'] || reload
377
+ options[:layout_breakpoints][:height_breakpoints] = value[:height_breakpoints] || value['height_breakpoints'] || height_breakpoints
378
+ else
379
+ options[:layout_breakpoints] = {
380
+ breakpoints: value,
381
+ reload: reload,
382
+ height_breakpoints: height_breakpoints
383
+ }
384
+ end
385
+ self
386
+ end
387
+
388
+ def wait_before_capture(value)
389
+ Applitools::ArgumentGuard.not_nil(value, 'wait_before_capture')
390
+ options[:wait_before_capture] = value
391
+ self
392
+ end
393
+
394
+ def page_id(value)
395
+ Applitools::ArgumentGuard.not_nil(value, 'page_id')
396
+ options[:page_id] = value
397
+ self
398
+ end
399
+
400
+ def lazy_load(*args) # scroll_length, waiting_time, max_amount_to_scroll
401
+ options[:lazy_load] = args.is_a?(Hash) ? args : true
402
+ self
403
+ end
404
+
401
405
  private
402
406
 
403
407
  def reset_for_fullscreen
@@ -409,6 +413,7 @@ module Applitools
409
413
  reset_layout_regions
410
414
  reset_strict_regions
411
415
  reset_accessibility_regions
416
+ reset_dynamic_regions
412
417
  options[:stitch_content] = nil
413
418
  options[:timeout] = nil
414
419
  options[:trim] = false
@@ -418,6 +423,10 @@ module Applitools
418
423
  self.accessibility_regions = []
419
424
  end
420
425
 
426
+ def reset_dynamic_regions
427
+ self.dynamic_regions = []
428
+ end
429
+
421
430
  def reset_ignore
422
431
  self.ignored_regions = []
423
432
  end
@@ -448,6 +457,94 @@ module Applitools
448
457
  xpath = driver.execute_script(Applitools::Selenium::Scripts::GET_ELEMENT_XPATH_JS, selenium_element)
449
458
  driver.find_element(:xpath, xpath)
450
459
  end
460
+
461
+ def get_requested_padding(padding, args)
462
+ return padding.to_hash if padding && padding.is_a?(Applitools::PaddingBounds)
463
+ return padding if padding && (padding.is_a?(Hash) || padding.is_a?(Numeric))
464
+ if args.last.is_a? Applitools::PaddingBounds
465
+ args.pop
466
+ # elsif args.last.is_a?(Applitools::FloatingBounds)
467
+ # args.pop.to_hash
468
+ else
469
+ {}
470
+ end
471
+ end
472
+
473
+ def get_bounds(args)
474
+ return args.pop.to_hash if args.last.is_a?(Applitools::FloatingBounds)
475
+ last4 = args.last(4)
476
+ if last4.size === 4 && last4.all? { |e| e.is_a?(Numeric) }
477
+ FloatingBounds.new(*last4).to_hash
478
+ else
479
+ {}
480
+ end
481
+ end
482
+
483
+ def region_from_args(args)
484
+ options = Applitools::Utils.extract_options!(args)
485
+ padding = options && options[:padding]
486
+ requested_padding = get_requested_padding(padding, args)
487
+ value = convert_to_universal(args)
488
+ value = { type: args[0], selector: args[1] } if value.nil?
489
+ value = value[:selector] if value.is_a?(Hash) && (value[:type].to_s === 'id')
490
+ return nil if value === {selector: nil, type: nil}
491
+ region = { region: value }
492
+ region.merge!(padding: requested_padding) if requested_padding != {}
493
+ region.merge!(regionId: options[:region_id]) if options[:region_id]
494
+ region
495
+ end
496
+
497
+
498
+ def is_element?(el)
499
+ el.is_a?(::Selenium::WebDriver::Element) || (el.is_a?(Applitools::Selenium::Element) && el.respond_to?(:ref))
500
+ end
501
+
502
+ def is_region?(region)
503
+ region.is_a?(Applitools::FloatingRegion) || region.is_a?(Applitools::Region) # || region.is_a?(Applitools::Selenium::Element)
504
+ end
505
+
506
+ def is_finder?(finders)
507
+ return false unless finders.is_a?(Array)
508
+ return false unless finders[1]
509
+ return true if [:uiautomator, :predicate, :accessibility_id].include?(finders[0].to_sym)
510
+ Applitools::Selenium::Driver::FINDERS.has_key?(finders[0].to_sym)
511
+ end
512
+
513
+ def convert_to_universal(args)
514
+ if is_element?(args.first)
515
+ ref = args.first.ref
516
+ ref = args.first.ref[1] if ref.is_a?(Array) && ref[0] === :element
517
+ return { elementId: ref }
518
+ end
519
+ return args.first.to_hash if is_region?(args.first)
520
+ if is_finder?(args)
521
+ if Applitools::Selenium::Driver::FINDERS.has_key?(args[0])
522
+ selector = args[1]
523
+ selector = "##{args[1]}" if args[0] === :id && !args[1].start_with?('#') && instance_of?(Applitools::Selenium::Target)
524
+ return {type: Applitools::Selenium::Driver::FINDERS[args[0]], selector: selector}
525
+ end
526
+ case args[0]
527
+ when :uiautomator # ANDROID_UI_AUTOMATOR: '-android uiautomator'
528
+ return {type: '-android uiautomator', selector: args[1]}
529
+ when :predicate # IOS_PREDICATE: '-ios predicate string',
530
+ return {type: '-ios predicate string', selector: args[1]}
531
+ when :accessibility_id
532
+ return {type: 'accessibility id', selector: args[1]}
533
+ end
534
+ end
535
+ if args.first.is_a?(String)
536
+ return proc { |driver| driver.find_element(name_or_id: args.first) }
537
+ end
538
+ if args.first.is_a?(Hash) && args.first.has_key?('selector')
539
+ if args.first.has_key?('shadow')
540
+ return {selector: args.first['selector'], shadow: args.first['shadow']}
541
+ else
542
+ return {selector: args.first['selector']}
543
+ end
544
+ end
545
+ nil
546
+ end
547
+
451
548
  end
452
549
  end
453
550
  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
@@ -48,7 +48,8 @@ module Applitools
48
48
  end
49
49
 
50
50
  def process_page_script
51
- Applitools::Selenium::Scripts::PROCESS_PAGE_AND_POLL
51
+ ''
52
+ # Applitools::Selenium::Scripts::PROCESS_PAGE_AND_POLL
52
53
  end
53
54
 
54
55
  def script_options
@@ -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,38 +1,6 @@
1
+ require_relative 'ios_device_name_generated'
2
+
1
3
  module IosDeviceName
4
+ include IosDeviceNameGenerated
2
5
  extend self
3
- IPhone_12_Pro_Max = 'iPhone 12 Pro Max'
4
- IPhone_12_Pro = 'iPhone 12 Pro'
5
- IPhone_12 = 'iPhone 12'
6
- IPhone_12_mini = 'iPhone 12 mini'
7
- IPhone_11_Pro = 'iPhone 11 Pro'
8
- IPhone_11_Pro_Max = 'iPhone 11 Pro Max'
9
- IPhone_11 = 'iPhone 11'
10
- IPhone_XR = 'iPhone XR'
11
- IPhone_XS = 'iPhone Xs'
12
- IPhone_X = 'iPhone X'
13
- IPhone_8 = 'iPhone 8'
14
- IPhone_7 = 'iPhone 7'
15
- IPad_Pro_3 = 'iPad Pro (12.9-inch) (3rd generation)'
16
- IPad_7 = 'iPad (7th generation)'
17
- IPad_Air_2 = 'iPad Air (2nd generation)'
18
-
19
- def enum_values
20
- [
21
- IPhone_12_Pro_Max,
22
- IPhone_12_Pro,
23
- IPhone_12,
24
- IPhone_12_mini,
25
- IPhone_11_Pro,
26
- IPhone_11_Pro_Max,
27
- IPhone_11,
28
- IPhone_XR,
29
- IPhone_XS,
30
- IPhone_X,
31
- IPhone_8,
32
- IPhone_7,
33
- IPad_Pro_3,
34
- IPad_7,
35
- IPad_Air_2
36
- ]
37
- end
38
6
  end