eyes_core 3.14.3 → 3.14.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +5 -5
  2. data/ext/eyes_core/extconf.rb +2 -0
  3. data/ext/eyes_core/eyes_core.c +7 -7
  4. data/ext/eyes_core/eyes_core.h +1 -6
  5. data/lib/applitools/appium/eyes.rb +12 -0
  6. data/lib/applitools/appium/initialize_1.9.rb +22 -0
  7. data/lib/applitools/appium/initialize_2.0.rb +17 -0
  8. data/lib/applitools/appium/utils.rb +44 -0
  9. data/lib/applitools/calabash/calabash_element.rb +2 -0
  10. data/lib/applitools/calabash/calabash_screenshot_provider.rb +2 -0
  11. data/lib/applitools/calabash/environment_detector.rb +2 -0
  12. data/lib/applitools/calabash/eyes.rb +5 -3
  13. data/lib/applitools/calabash/eyes_calabash_android_screenshot.rb +13 -2
  14. data/lib/applitools/calabash/eyes_calabash_ios_screenshot.rb +2 -0
  15. data/lib/applitools/calabash/eyes_calabash_screenshot.rb +2 -0
  16. data/lib/applitools/calabash/eyes_hooks.rb +2 -0
  17. data/lib/applitools/calabash/eyes_settings.rb +2 -0
  18. data/lib/applitools/calabash/full_page_capture_algorithm.rb +2 -0
  19. data/lib/applitools/calabash/full_page_capture_algorithm/android_scroll_view.rb +12 -2
  20. data/lib/applitools/calabash/full_page_capture_algorithm/base.rb +2 -0
  21. data/lib/applitools/calabash/full_page_capture_algorithm/ios_ui_table_view.rb +2 -0
  22. data/lib/applitools/calabash/os_versions.rb +2 -0
  23. data/lib/applitools/calabash/rspec_matchers.rb +2 -0
  24. data/lib/applitools/calabash/steps/android_eyes_session.rb +2 -0
  25. data/lib/applitools/calabash/steps/android_matchers.rb +2 -0
  26. data/lib/applitools/calabash/steps/eyes_session.rb +2 -0
  27. data/lib/applitools/calabash/steps/eyes_settings.rb +2 -0
  28. data/lib/applitools/calabash/steps/ios_eyes_session.rb +2 -0
  29. data/lib/applitools/calabash/steps/ios_matchers.rb +2 -0
  30. data/lib/applitools/calabash/steps/matchers.rb +2 -0
  31. data/lib/applitools/calabash/target.rb +2 -0
  32. data/lib/applitools/calabash/utils.rb +2 -0
  33. data/lib/applitools/calabash_steps.rb +2 -0
  34. data/lib/applitools/capybara/capybara_settings.rb +25 -0
  35. data/lib/applitools/capybara/driver.rb +39 -0
  36. data/lib/applitools/chunky_png/resampling.rb +2 -0
  37. data/lib/applitools/chunky_png_patch.rb +2 -0
  38. data/lib/applitools/connectivity/proxy.rb +2 -0
  39. data/lib/applitools/connectivity/server_connector.rb +23 -1
  40. data/lib/applitools/core/abstract_region.rb +2 -0
  41. data/lib/applitools/core/app_environment.rb +2 -0
  42. data/lib/applitools/core/app_output.rb +16 -4
  43. data/lib/applitools/core/app_output_with_screenshot.rb +2 -0
  44. data/lib/applitools/core/argument_guard.rb +3 -1
  45. data/lib/applitools/core/batch_info.rb +13 -5
  46. data/lib/applitools/core/class_name.rb +2 -0
  47. data/lib/applitools/core/debug_screenshot_provider.rb +4 -2
  48. data/lib/applitools/core/eyes_base.rb +45 -9
  49. data/lib/applitools/core/eyes_screenshot.rb +10 -1
  50. data/lib/applitools/core/fixed_cut_provider.rb +2 -0
  51. data/lib/applitools/core/fixed_scale_provider.rb +2 -0
  52. data/lib/applitools/core/floating_region.rb +10 -0
  53. data/lib/applitools/core/fluent_interface.rb +8 -1
  54. data/lib/applitools/core/hash_extension.rb +2 -0
  55. data/lib/applitools/core/helpers.rb +24 -0
  56. data/lib/applitools/core/location.rb +19 -1
  57. data/lib/applitools/core/match_level_setter.rb +2 -0
  58. data/lib/applitools/core/match_result.rb +2 -0
  59. data/lib/applitools/core/match_results.rb +2 -0
  60. data/lib/applitools/core/match_single_check_data.rb +2 -0
  61. data/lib/applitools/core/match_single_task.rb +2 -0
  62. data/lib/applitools/core/match_window_data.rb +26 -4
  63. data/lib/applitools/core/match_window_task.rb +2 -0
  64. data/lib/applitools/core/mouse_trigger.rb +2 -0
  65. data/lib/applitools/core/padding_bounds.rb +2 -0
  66. data/lib/applitools/core/rectangle_size.rb +16 -0
  67. data/lib/applitools/core/region.rb +32 -9
  68. data/lib/applitools/core/region_provider.rb +2 -0
  69. data/lib/applitools/core/screenshot.rb +6 -0
  70. data/lib/applitools/core/session.rb +2 -0
  71. data/lib/applitools/core/session_start_info.rb +2 -0
  72. data/lib/applitools/core/test_results.rb +2 -0
  73. data/lib/applitools/core/text_trigger.rb +2 -0
  74. data/lib/applitools/core/trigger.rb +2 -0
  75. data/lib/applitools/extensions.rb +2 -0
  76. data/lib/applitools/eyes_logger.rb +4 -2
  77. data/lib/applitools/method_tracer.rb +2 -0
  78. data/lib/applitools/rspec/target_matcher.rb +2 -0
  79. data/lib/applitools/sauce.rb +2 -1
  80. data/lib/applitools/utils/eyes_selenium_utils.rb +91 -15
  81. data/lib/applitools/utils/image_delta_compressor.rb +2 -0
  82. data/lib/applitools/utils/image_utils.rb +2 -0
  83. data/lib/applitools/utils/utils.rb +14 -0
  84. data/lib/applitools/version.rb +3 -1
  85. data/lib/eyes_core.rb +2 -0
  86. data/lib/eyes_rspec.rb +4 -0
  87. data/lib/require_utils.rb +2 -0
  88. metadata +10 -4
  89. data/lib/applitools/capybara.rb +0 -8
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined? Capybara::Selenium::Driver
4
+ module Applitools::Selenium::Capybara
5
+ # @!visibility private
6
+ class Driver < Capybara::Selenium::Driver
7
+ def driver_for_eyes(eyes)
8
+ browser eyes: eyes
9
+ end
10
+
11
+ def browser(options = {})
12
+ eyes = options.delete(:eyes)
13
+ @native_browser ||= super()
14
+ unless eyes.nil?
15
+ is_mobile_device = @browser.capabilities['platformName'] ? true : false
16
+ @browser = Applitools::Selenium::Driver.new eyes,
17
+ options.merge(driver: @browser, is_mobile_device: is_mobile_device)
18
+ end
19
+ @browser
20
+ end
21
+
22
+ def use_native_browser
23
+ @browser = @native_browser
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ if defined? ::Capybara::Session
30
+ ::Capybara::Session.class_eval do
31
+ def driver_for_eyes(eyes)
32
+ driver.driver_for_eyes eyes
33
+ end
34
+
35
+ def use_native_browser
36
+ driver.use_native_browser if driver.respond_to? :use_native_browser
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class Enumerator < ::Enumerator
3
5
  if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'oily_png'
2
4
  # require 'chunky_png'
3
5
  require_relative 'chunky_png/resampling'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools::Connectivity
2
4
  Proxy = Struct.new(:uri, :user, :password) do
3
5
  def to_hash
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  require 'faraday'
2
4
  require 'oj'
3
5
  Oj.default_options = { :mode => :compat }
@@ -6,6 +8,7 @@ require 'uri'
6
8
 
7
9
  module Applitools::Connectivity
8
10
  class ServerConnector
11
+ extend Applitools::Helpers
9
12
  DEFAULT_SERVER_URL = 'https://eyessdk.applitools.com'.freeze
10
13
 
11
14
  SSL_CERT = File.join(File.dirname(File.expand_path(__FILE__)), '../../../certs/cacert.pem').to_s.freeze
@@ -21,9 +24,10 @@ module Applitools::Connectivity
21
24
  gone: 410
22
25
  }.freeze
23
26
 
24
- attr_accessor :server_url, :api_key
27
+ attr_accessor :server_url
25
28
  attr_reader :endpoint_url
26
29
  attr_reader :proxy
30
+ environment_attribute :api_key, 'APPLITOOLS_API_KEY'
27
31
 
28
32
  def initialize(url = nil)
29
33
  self.server_url = url
@@ -120,6 +124,24 @@ module Applitools::Connectivity
120
124
  Applitools::TestResults.new(response)
121
125
  end
122
126
 
127
+ def post_dom_json(dom_data)
128
+ Applitools::EyesLogger.debug 'About to send captured DOM...'
129
+ request_body = Oj.dump(dom_data)
130
+ Applitools::EyesLogger.debug request_body
131
+ processed_request_body = yield(request_body) if block_given?
132
+ res = post(
133
+ endpoint_url + 'data',
134
+ body: processed_request_body.nil? ? request_body : processed_request_body,
135
+ content_type: 'application/octet-stream'
136
+ )
137
+
138
+ Applitools::EyesLogger.debug 'Done!'
139
+ raise Applitools::EyesError.new("Request failed: #{res.status} #{res.body}") unless res.success?
140
+ Applitools::EyesLogger.debug 'Server response headers:'
141
+ Applitools::EyesLogger.debug res.headers.inspect
142
+ res.headers['location']
143
+ end
144
+
123
145
  private
124
146
 
125
147
  DEFAULT_HEADERS = {
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class AbstractRegion
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module Applitools
2
4
  class AppEnvironment
3
5
  attr_accessor :os, :hosting_app, :display_size, :inferred_environment
@@ -1,17 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class AppOutput
3
- attr_reader :title, :screenshot64
5
+ attr_reader :title, :screenshot64, :location
6
+ attr_accessor :dom_url
4
7
 
5
8
  def initialize(title, screenshot64)
6
9
  @title = title
7
10
  @screenshot64 = screenshot64
11
+ @location = Applitools::Location::TOP_LEFT
12
+ end
13
+
14
+ def location=(value)
15
+ Applitools::ArgumentGuard.is_a?(value, 'location', Applitools::Location)
16
+ @location = value
8
17
  end
9
18
 
10
19
  def to_hash
11
- {
12
- title: title,
13
- screenshot64: nil
20
+ result = {
21
+ Title: title,
22
+ Screenshot64: nil,
23
+ Location: location.to_hash
14
24
  }
25
+ result[:DomUrl] = dom_url if dom_url
26
+ result
15
27
  end
16
28
  end
17
29
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class AppOutputWithScreenshot
3
5
  attr_reader :app_output, :screenshot
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  module ArgumentGuard
3
5
  extend self
@@ -29,7 +31,7 @@ module Applitools
29
31
  def is_a?(param, param_name, klass)
30
32
  return true if param.is_a? klass
31
33
  raise Applitools::EyesIllegalArgument.new "Expected #{param_name} to be" \
32
- " instance of #{klass} (but got #{param.class.name})"
34
+ " instance of #{klass}, but got #{param.class.name} instead"
33
35
  end
34
36
 
35
37
  def raise_argument_error(error)
@@ -1,18 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'securerandom'
4
+ require_relative 'helpers'
2
5
 
3
6
  module Applitools
4
7
  class BatchInfo
5
- attr_accessor :name, :started_at, :id
8
+ extend Helpers
9
+ attr_accessor :started_at, :id
10
+
11
+ environment_attribute :name, 'APPLITOOLS_BATCH_NAME'
12
+ environment_attribute :id, 'APPLITOOLS_BATCH_ID'
13
+
6
14
  def initialize(name = nil, started_at = Time.now)
7
- @name = name
15
+ self.name = name if name
8
16
  @started_at = started_at
9
- @id = SecureRandom.uuid
17
+ self.id = SecureRandom.uuid unless id
10
18
  end
11
19
 
12
20
  def to_hash
13
21
  {
14
- 'id' => @id,
15
- 'name' => @name,
22
+ 'id' => id,
23
+ 'name' => name,
16
24
  'startedAt' => @started_at.iso8601
17
25
  }
18
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class ClassName < String
3
5
  def ===(other)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
 
3
5
  module Applitools
@@ -12,9 +14,9 @@ module Applitools
12
14
  return unless debug
13
15
  case image
14
16
  when ::ChunkyPNG::Image, Applitools::Screenshot
15
- image.save(file_name_to_save(suffix))
17
+ image.save(file_name_to_save(suffix)) if image.area > 0
16
18
  when Applitools::EyesScreenshot
17
- image.image.save(file_name_to_save(suffix))
19
+ image.image.save(file_name_to_save(suffix)) if image.image.area > 0
18
20
  when String
19
21
  ::ChunkyPNG::Image.from_string(image).save(file_name_to_save(suffix))
20
22
  else
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'applitools/core/helpers'
2
4
  require 'applitools/core/eyes_screenshot'
5
+ require 'zlib'
6
+
3
7
  require_relative 'match_level_setter'
4
8
 
5
9
  module Applitools
@@ -32,9 +36,9 @@ module Applitools
32
36
  # Default value is false.
33
37
  # @return [boolean] verbose_results flag
34
38
 
35
- attr_accessor :app_name, :baseline_name, :branch_name, :parent_branch_name, :batch, :agent_id, :full_agent_id,
39
+ attr_accessor :app_name, :batch, :agent_id, :full_agent_id,
36
40
  :match_timeout, :save_new_tests, :save_failed_tests, :failure_reports, :default_match_settings, :cut_provider,
37
- :scale_ratio, :host_os, :host_app, :base_line_name, :position_provider, :viewport_size, :verbose_results,
41
+ :scale_ratio, :host_os, :host_app, :position_provider, :viewport_size, :verbose_results,
38
42
  :inferred_environment, :remove_session_if_matching, :server_scale, :server_remainder, :match_level, :exact,
39
43
  :compare_with_parent_branch
40
44
 
@@ -44,6 +48,10 @@ module Applitools
44
48
  abstract_method :set_viewport_size, true
45
49
  abstract_method :get_viewport_size, true
46
50
 
51
+ environment_attribute :branch_name, 'APPLITOOLS_BRANCH'
52
+ environment_attribute :parent_branch_name, 'APPLITOOLS_PARENT_BRANCH'
53
+ environment_attribute :baseline_env_name, 'APPLITOOLS_BASELINE_BRANCH'
54
+
47
55
  def initialize(server_url = nil)
48
56
  self.server_connector = Applitools::Connectivity::ServerConnector.new(server_url)
49
57
  self.disabled = false
@@ -331,7 +339,7 @@ module Applitools
331
339
 
332
340
  session_start_info = SessionStartInfo.new agent_id: base_agent_id, app_id_or_name: app_name,
333
341
  scenario_id_or_name: test_name, batch_info: batch,
334
- env_name: baseline_name, environment: app_environment,
342
+ env_name: baseline_env_name, environment: app_environment,
335
343
  default_match_settings: default_match_settings,
336
344
  branch_name: branch_name, parent_branch_name: parent_branch_name, properties: properties
337
345
 
@@ -394,7 +402,7 @@ module Applitools
394
402
  # @param [Boolean] throw_exception If set to +true+ eyes will trow [Applitools::TestFailedError] exception,
395
403
  # otherwise the test will pass. Default is true
396
404
 
397
- def close(throw_exception = true)
405
+ def close(throw_exception = true, be_silent = false)
398
406
  if disabled?
399
407
  logger.info "#{__method__} Ignored"
400
408
  return false
@@ -409,8 +417,8 @@ module Applitools
409
417
  clear_user_inputs
410
418
 
411
419
  unless running_session
412
- logger.info 'Server session was not started'
413
- logger.info '--- Empty test ended'
420
+ be_silent || logger.info('Server session was not started')
421
+ be_silent || logger.info('--- Empty test ended')
414
422
  return Applitools::TestResults.new
415
423
  end
416
424
 
@@ -476,6 +484,10 @@ module Applitools
476
484
 
477
485
  private :full_agent_id, :full_agent_id=
478
486
 
487
+ def dom_data
488
+ {}
489
+ end
490
+
479
491
  def match_level_keys
480
492
  %w(match_level exact scale remainder).map(&:to_sym)
481
493
  end
@@ -592,8 +604,8 @@ module Applitools
592
604
  logger.info "Application environment is #{app_env}"
593
605
 
594
606
  self.session_start_info = SessionStartInfo.new agent_id: base_agent_id, app_id_or_name: app_name,
595
- scenario_id_or_name: test_name, batch_info: @batch,
596
- env_name: baseline_name, environment: app_env,
607
+ scenario_id_or_name: test_name, batch_info: batch,
608
+ env_name: baseline_env_name, environment: app_env,
597
609
  default_match_settings: default_match_settings,
598
610
  branch_name: branch_name, parent_branch_name: parent_branch_name,
599
611
  properties: properties
@@ -613,6 +625,27 @@ module Applitools
613
625
  end
614
626
 
615
627
  def get_app_output_with_screenshot(region_provider, last_screenshot)
628
+ dom_url = ''
629
+ captured_dom_data = dom_data
630
+ unless captured_dom_data.empty?
631
+ begin
632
+ logger.info 'Processing DOM..'
633
+ dom_url = server_connector.post_dom_json(captured_dom_data) do |json|
634
+ io = StringIO.new
635
+ gz = Zlib::GzipWriter.new(io)
636
+ gz.write(json.encode('UTF-8'))
637
+ gz.close
638
+ result = io.string
639
+ io.close
640
+ result
641
+ end
642
+ logger.info 'Done'
643
+ logger.info dom_url
644
+ rescue Applitools::EyesError => e
645
+ logger.warn e.message
646
+ dom_url = nil
647
+ end
648
+ end
616
649
  logger.info 'Getting screenshot...'
617
650
  screenshot = capture_screenshot
618
651
  logger.info 'Done getting screenshot!'
@@ -630,7 +663,10 @@ module Applitools
630
663
  a_title = title
631
664
  logger.info 'Done!'
632
665
  Applitools::AppOutputWithScreenshot.new(
633
- Applitools::AppOutput.new(a_title, compress_result),
666
+ Applitools::AppOutput.new(a_title, compress_result).tap do |o|
667
+ o.location = region.location unless region.empty?
668
+ o.dom_url = dom_url unless dom_url && dom_url.empty?
669
+ end,
634
670
  screenshot
635
671
  )
636
672
  end
@@ -1,10 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class EyesScreenshot
3
5
  extend Forwardable
4
6
  extend Applitools::Helpers
5
7
 
6
8
  def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
7
- attr_accessor :image
9
+ attr_accessor :image, :top_left_location
10
+ def_delegators '@image', :width, :height
8
11
 
9
12
  COORDINATE_TYPES = {
10
13
  context_as_is: 'CONTEXT_AS_IS',
@@ -39,5 +42,11 @@ module Applitools
39
42
  updated_location = convert_location(region.location, from, to)
40
43
  Region.new updated_location.x, updated_location.y, region.width, region.height
41
44
  end
45
+
46
+ private
47
+
48
+ def image_region
49
+ Applitools::Region.new(0, 0, image.width, image.height)
50
+ end
42
51
  end
43
52
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  # Provides 'cut' method which is used to cut screen shots
3
5
  class FixedCutProvider
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  # @!visibility private
3
5
  class FixedScaleProvider
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'region'
2
4
  module Applitools
3
5
  class FloatingRegion < Region
@@ -81,6 +83,14 @@ module Applitools
81
83
  self
82
84
  end
83
85
 
86
+ def ==(other)
87
+ super(other) &&
88
+ max_left_offset == other.max_left_offset &&
89
+ max_top_offset == other.max_top_offset &&
90
+ max_right_offset == other.max_right_offset &&
91
+ max_bottom_offset == other.max_bottom_offset
92
+ end
93
+
84
94
  def to_hash
85
95
  {
86
96
  'Top' => top,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'match_level_setter'
2
4
  module Applitools::FluentInterface
3
5
  include Applitools::MatchLevelSetter
@@ -9,7 +11,7 @@ module Applitools::FluentInterface
9
11
  end
10
12
  end
11
13
 
12
- def ignore_caret(value = false)
14
+ def ignore_caret(value = true)
13
15
  options[:ignore_caret] = value ? true : false
14
16
  self
15
17
  end
@@ -42,4 +44,9 @@ module Applitools::FluentInterface
42
44
  options[:match_level], options[:exact] = match_level_with_exact(value, exact_options)
43
45
  self
44
46
  end
47
+
48
+ def send_dom(value)
49
+ options[:send_dom] = value ? true : false
50
+ self
51
+ end
45
52
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools::HashExtension
2
4
  if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
3
5
  def struct_define_to_h_method