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
@@ -1,5 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  module Helpers
5
+ @environment_variables = {}
6
+
7
+ def self.environment_variables
8
+ @environment_variables
9
+ end
10
+
3
11
  def abstract_attr_accessor(*names)
4
12
  names.each do |method_name|
5
13
  instance_variable_set "@#{method_name}", nil
@@ -14,5 +22,21 @@ module Applitools
14
22
  end
15
23
  private method_name if is_private
16
24
  end
25
+
26
+ def environment_attribute(attribute_name, environment_variable)
27
+ class_eval do
28
+ Applitools::Helpers.environment_variables[environment_variable.to_sym] = ENV[environment_variable.to_s] if
29
+ ENV[environment_variable.to_s]
30
+ attr_accessor attribute_name
31
+ define_method(attribute_name) do
32
+ current_value = instance_variable_get "@#{attribute_name}".to_sym
33
+ return current_value if current_value
34
+ instance_variable_set(
35
+ "@#{attribute_name}".to_sym,
36
+ Applitools::Helpers.environment_variables[environment_variable.to_sym]
37
+ )
38
+ end
39
+ end
40
+ end
17
41
  end
18
42
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'applitools/core/region'
2
4
  module Applitools
3
5
  class Location
@@ -44,7 +46,7 @@ module Applitools
44
46
  @y = y
45
47
  end
46
48
 
47
- TOP_LEFT = Location.new(0, 0)
49
+ TOP_LEFT = Location.new(0, 0).freeze
48
50
 
49
51
  def to_s
50
52
  "#{x} x #{y}"
@@ -55,12 +57,28 @@ module Applitools
55
57
  @x == other.x && @y == other.y
56
58
  end
57
59
 
60
+ def !=(other)
61
+ !(self == other)
62
+ end
63
+
58
64
  alias eql? ==
59
65
 
60
66
  def hash
61
67
  @x.hash & @y.hash
62
68
  end
63
69
 
70
+ def negative_part
71
+ new_x = @x < 0 ? @x : 0
72
+ new_y = @y < 0 ? @y : 0
73
+ self.class.new(new_x.round, new_y.round)
74
+ end
75
+
76
+ def positive_part
77
+ new_x = @x < 0 ? 0 : @x
78
+ new_y = @y < 0 ? 0 : @y
79
+ self.class.new(new_x.round, new_y.round)
80
+ end
81
+
64
82
  def to_hash(options = {})
65
83
  options[:region] ? { left: left, top: top } : { x: x, y: y }
66
84
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools::MatchLevelSetter
2
4
  def match_level_with_exact(value, exact_options = {})
3
5
  raise Applitools::EyesError unless Applitools::MATCH_LEVEL.keys.include? value
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class MatchResult
3
5
  attr_reader :response_hash
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class MatchResults
3
5
  attr_accessor :screenshot, :window_id, :as_expected
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'match_window_data'
2
4
  module Applitools
3
5
  class MatchSingleCheckData < MatchWindowData
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  require_relative 'match_window_task'
3
5
  module Applitools
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class MatchWindowData
3
5
  class << self
@@ -48,7 +50,11 @@ module Applitools
48
50
  'ScreenshotUrl' => nil,
49
51
  'Title' => nil,
50
52
  'IsPrimary' => false,
51
- 'Elapsed' => 0
53
+ 'Elapsed' => 0,
54
+ 'Location' => {
55
+ 'X' => 0,
56
+ 'Y' => 0
57
+ }
52
58
  },
53
59
  'Tag' => nil
54
60
  }
@@ -111,9 +117,15 @@ module Applitools
111
117
  def app_output=(value)
112
118
  Applitools::ArgumentGuard.is_a? value, 'value', Applitools::AppOutputWithScreenshot
113
119
  @app_output = value
114
- hash_value = value.to_hash
115
- %w(Screenshot64 ScreenshotUrl Title IsPrimary Elapsed).each do |key|
116
- current_data['AppOutput'][key] = hash_value[key] unless hash_value[key].nil?
120
+ hash_value = Applitools::Utils.capitalize_hash_keys(value.to_hash)
121
+ [:Screenshot64, :ScreenshotUrl, :Title, :IsPrimary, :Elapsed, :Location, :DomUrl].each do |key|
122
+ next if hash_value[key].nil?
123
+ current_data['AppOutput'][key.to_s] = case hash_value[key]
124
+ when Hash
125
+ Hash[hash_value[key].map { |k, v| [k.to_s, v] }]
126
+ else
127
+ hash_value[key]
128
+ end
117
129
  end
118
130
  end
119
131
 
@@ -231,6 +243,16 @@ module Applitools
231
243
  Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
232
244
  )
233
245
  updated_region.to_hash
246
+ Applitools::FloatingRegion.new(
247
+ updated_region.left,
248
+ updated_region.top,
249
+ r.width,
250
+ r.height,
251
+ r.max_left_offset,
252
+ r.max_top_offset,
253
+ r.max_right_offset,
254
+ r.max_bottom_offset
255
+ ).padding(r.current_padding)
234
256
  end
235
257
  @need_convert_floating_regions_coordinates = false
236
258
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  module Applitools
3
5
  class MatchWindowTask
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'applitools/core/trigger'
2
4
  module Applitools
3
5
  class MouseTrigger < Trigger
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class PaddingBounds
3
5
  attr_accessor :padding_left, :padding_top, :padding_right, :padding_bottom
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'hash_extension'
2
4
  module Applitools
5
+ # rubocop:disable Metrics/BlockLength
3
6
  RectangleSize = Struct.new(:width, :height) do
4
7
  include Applitools::HashExtension
5
8
  class << self
@@ -54,8 +57,21 @@ module Applitools
54
57
  self
55
58
  end
56
59
 
60
+ def square
61
+ width * height
62
+ end
63
+
64
+ def >(other)
65
+ square > other.square
66
+ end
67
+
68
+ def<(other)
69
+ square < other.square
70
+ end
71
+
57
72
  def to_hash
58
73
  to_h
59
74
  end
60
75
  end
76
+ # rubocop:enable Metrics/BlockLength
61
77
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'padding_bounds'
2
4
  module Applitools
3
5
  class Region
4
6
  extend Forwardable
5
- attr_accessor :left, :top, :width, :height
7
+ attr_accessor :left, :top, :width, :height, :padding
6
8
 
7
9
  def_delegators :@padding, :padding_left, :padding_top, :padding_right, :padding_bottom
8
10
 
@@ -65,8 +67,7 @@ module Applitools
65
67
  def intersect(other)
66
68
  unless intersecting?(other)
67
69
  make_empty
68
-
69
- return
70
+ return self
70
71
  end
71
72
 
72
73
  i_left = left >= other.left ? left : other.left
@@ -121,6 +122,16 @@ module Applitools
121
122
  width == region.width && height == region.height
122
123
  end
123
124
 
125
+ def ==(other)
126
+ return false unless other.is_a? self.class
127
+ size_location_match = left == other.left && top == other.top && width == other.width && height == other.height
128
+ padding_match = padding_left == other.padding_left &&
129
+ padding_top == other.padding_top &&
130
+ padding_right == other.padding_right &&
131
+ padding_bottom == other.padding_bottom
132
+ size_location_match && padding_match
133
+ end
134
+
124
135
  # Sets padding for a current region. If called without any argument, all paddings will be set to 0
125
136
  # @param padding[Applitools::PaddingBounds] represents paddings to be set for a region
126
137
  # @return [Applitools::Region]
@@ -131,6 +142,10 @@ module Applitools
131
142
  self
132
143
  end
133
144
 
145
+ def current_padding
146
+ @padding
147
+ end
148
+
134
149
  def with_padding
135
150
  Applitools::Region.from_location_size(
136
151
  Applitools::Location.new(left - padding_left, top - padding_top),
@@ -139,6 +154,7 @@ module Applitools
139
154
  end
140
155
 
141
156
  class << self
157
+ DEFAULT_SUBREGIONS_INTERSECTION = 4
142
158
  def sub_regions_with_fixed_size(container_region, sub_region)
143
159
  Applitools::ArgumentGuard.not_nil container_region, 'container_region'
144
160
  Applitools::ArgumentGuard.not_nil sub_region, 'sub_region'
@@ -155,7 +171,7 @@ module Applitools
155
171
 
156
172
  if sub_region_width == container_region.width && sub_region_height == container_region.height
157
173
  return Enumerator(1) do |y|
158
- y << sub_region
174
+ y << [sub_region, EMPTY]
159
175
  end
160
176
  end
161
177
 
@@ -168,7 +184,7 @@ module Applitools
168
184
  current_left = container_region.left
169
185
  while current_left <= right
170
186
  current_left = (rught - sub_region_width) + 1 if current_left + sub_region_width > right
171
- y << new(current_left, current_top, sub_region_width, sub_region_height)
187
+ y << [new(current_left, current_top, sub_region_width, sub_region_height), EMPTY]
172
188
  current_left += sub_region_width
173
189
  end
174
190
  current_top += sub_region_height
@@ -176,7 +192,7 @@ module Applitools
176
192
  end
177
193
  end
178
194
 
179
- def sub_regions_with_varying_size(container_region, sub_region)
195
+ def sub_regions_with_varying_size(container_region, sub_region, intersection = DEFAULT_SUBREGIONS_INTERSECTION)
180
196
  Applitools::ArgumentGuard.not_nil container_region, 'container_region'
181
197
  Applitools::ArgumentGuard.not_nil sub_region, 'sub_region'
182
198
 
@@ -186,12 +202,14 @@ module Applitools
186
202
  current_top = container_region.top
187
203
  bottom = container_region.top + container_region.height
188
204
  right = container_region.left + container_region.width
205
+ top_intersect = 0
189
206
 
190
207
  Enumerator.new do |y|
191
208
  while current_top < bottom
192
209
  current_bottom = current_top + sub_region.height
193
210
  current_bottom = bottom if current_bottom > bottom
194
211
  current_left = container_region.left
212
+ left_intersect = 0
195
213
  while current_left < right
196
214
  current_right = current_left + sub_region.width
197
215
  current_right = right if current_right > right
@@ -199,11 +217,16 @@ module Applitools
199
217
  current_height = current_bottom - current_top
200
218
  current_width = current_right - current_left
201
219
 
202
- y << new(current_left, current_top, current_width, current_height)
220
+ y << [
221
+ new(current_left, current_top, current_width, current_height),
222
+ new(left_intersect, top_intersect, left_intersect, top_intersect)
223
+ ]
203
224
 
204
- current_left += sub_region.width
225
+ current_left += sub_region.width - intersection * 2
226
+ left_intersect = intersection if left_intersect.zero?
205
227
  end
206
- current_top += sub_region.height
228
+ current_top += sub_region.height - intersection * 2
229
+ top_intersect = intersection if top_intersect.zero?
207
230
  end
208
231
  end
209
232
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class RegionProvider
3
5
  # Do we need it under Selenium module?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class Screenshot < Delegator
3
5
  class << self
@@ -41,6 +43,10 @@ module Applitools
41
43
  super
42
44
  end
43
45
 
46
+ def square
47
+ width * height
48
+ end
49
+
44
50
  class Datastream < self
45
51
  extend Forwardable
46
52
  def_delegators :header, :width, :height
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class Session
3
5
  attr_reader :id, :url
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class SessionStartInfo
3
5
  attr_accessor :app_id_or_name, :scenario_id_or_name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
 
3
5
  module Applitools
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'applitools/core/trigger'
2
4
  module Applitools
3
5
  class TextTrigger < Trigger
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  class Trigger
3
5
  TRIGGER_TYPE = :unknown
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # @!visibility private
2
4
  class Module
3
5
  def alias_attribute(new_name, old_name)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
 
3
5
  module Applitools::EyesLogger
@@ -19,8 +21,8 @@ module Applitools::EyesLogger
19
21
  end
20
22
  end
21
23
 
22
- MANDATORY_METHODS = [:debug, :info, :close].freeze
23
- OPTIONAL_METHODS = [:warn, :error, :fatal].freeze
24
+ MANDATORY_METHODS = [:debug, :info, :warn, :error, :fatal, :close].freeze
25
+ OPTIONAL_METHODS = [].freeze
24
26
 
25
27
  def_delegators :@log_handler, *MANDATORY_METHODS
26
28
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # @!visibility private
2
4
  module Applitools::MethodTracer
3
5
  def self.included(base)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rspec/expectations'
2
4
 
3
5
  RSpec::Matchers.define :match_baseline do |expected, tag|
@@ -1,2 +1,3 @@
1
- require_relative 'capybara' if defined? Capybara
1
+ # frozen_string_literal: true
2
+
2
3
  Applitools::Selenium.require_dir 'selenium/sauce'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module Applitools::Utils
2
4
  module EyesSeleniumUtils
3
5
  extend self
@@ -77,6 +79,36 @@ module Applitools::Utils
77
79
  window.scrollTo(%{left}, %{top});
78
80
  JS
79
81
 
82
+ # IMPORTANT: Notice there's a major difference between scrollWidth
83
+ # and scrollHeight. While scrollWidth is the maximum between an
84
+ # element's width and its content width, scrollHeight might be
85
+ # smaller (!) than the clientHeight, which is why we take the
86
+ # maximum between them.
87
+
88
+ # @!visibility private
89
+ JS_COMPUTE_CONTENT_ENTIRE_SIZE = <<-JS.freeze
90
+ var scrollWidth = document.documentElement.scrollWidth;
91
+ var bodyScrollWidth = document.body.scrollWidth;
92
+ var totalWidth = Math.max(scrollWidth, bodyScrollWidth);
93
+ var clientHeight = document.documentElement.clientHeight;
94
+ var bodyClientHeight = document.body.clientHeight;
95
+ var scrollHeight = document.documentElement.scrollHeight;
96
+ var bodyScrollHeight = document.body.scrollHeight;
97
+ var maxDocElementHeight = Math.max(clientHeight, scrollHeight);
98
+ var maxBodyHeight = Math.max(bodyClientHeight, bodyScrollHeight);
99
+ var totalHeight = Math.max(maxDocElementHeight, maxBodyHeight);
100
+ JS
101
+
102
+ # @!visibility private
103
+ JS_RETURN_CONTENT_ENTIRE_SIZE = <<-JS.freeze
104
+ #{JS_COMPUTE_CONTENT_ENTIRE_SIZE}; return [totalWidth, totalHeight];
105
+ JS
106
+
107
+ # @!visibility private
108
+ JS_SCROLL_TO_BOTTOM_RIGHT = <<-JS.freeze
109
+ #{JS_COMPUTE_CONTENT_ENTIRE_SIZE}; window.scrollTo(totalWidth, totalHeight);
110
+ JS
111
+
80
112
  # @!visibility private
81
113
  JS_GET_CURRENT_TRANSFORM = <<-JS.freeze
82
114
  return document.body.style.transform;
@@ -100,12 +132,20 @@ module Applitools::Utils
100
132
  }());
101
133
  JS
102
134
 
135
+ # JS_GET_TRANSFORM_VALUE = <<-JS.freeze
136
+ # document.documentElement.style['%{key}']
137
+ # JS
138
+ #
139
+ # JS_SET_TRANSFORM_VALUE = <<-JS.freeze
140
+ # document.documentElement.style['%{key}'] = '%{value}'
141
+ # JS
142
+
103
143
  JS_GET_TRANSFORM_VALUE = <<-JS.freeze
104
- document.documentElement.style['%{key}']
144
+ %{element}.style['%{key}']
105
145
  JS
106
146
 
107
147
  JS_SET_TRANSFORM_VALUE = <<-JS.freeze
108
- document.documentElement.style['%{key}'] = '%{value}'
148
+ %{element}.style['%{key}'] = '%{value}'
109
149
  JS
110
150
 
111
151
  JS_TRANSFORM_KEYS = ['transform', '-webkit-transform'].freeze
@@ -127,23 +167,22 @@ module Applitools::Utils
127
167
 
128
168
  # true if test is running on mobile device
129
169
  def mobile_device?
130
- return nil unless defined?(Appium::Driver)
131
- return $driver if $driver && $driver.is_a?(Appium::Driver)
170
+ nil
132
171
  end
133
172
 
134
173
  # true if test is running on Android device
135
- def android?(driver)
136
- driver.respond_to?(:appium_device) && driver.appium_device == :android
174
+ def android?(_driver)
175
+ false
137
176
  end
138
177
 
139
178
  # true if test is running on iOS device
140
- def ios?(driver)
141
- driver.respond_to?(:appium_device) && driver.appium_device == :ios
179
+ def ios?(_driver)
180
+ false
142
181
  end
143
182
 
144
183
  # @param [Applitools::Selenium::Driver] driver
145
- def platform_version(driver)
146
- driver.respond_to?(:caps) && driver.caps[:platformVersion]
184
+ def platform_version(_driver)
185
+ nil
147
186
  end
148
187
 
149
188
  # @param [Applitools::Selenium::Driver] executor
@@ -207,8 +246,10 @@ module Applitools::Utils
207
246
  end
208
247
 
209
248
  def current_transforms(executor)
210
- script =
211
- "return { #{JS_TRANSFORM_KEYS.map { |tk| "'#{tk}': #{JS_GET_TRANSFORM_VALUE % { key: tk }}" }.join(', ')} };"
249
+ transform_script = JS_TRANSFORM_KEYS.map do |tk|
250
+ "'#{tk}': #{JS_GET_TRANSFORM_VALUE % { element: 'document.documentElement', key: tk }}"
251
+ end.join(', ')
252
+ script = "return { #{transform_script} };"
212
253
  executor.execute_script(script)
213
254
  end
214
255
 
@@ -219,12 +260,35 @@ module Applitools::Utils
219
260
  end
220
261
 
221
262
  def set_transforms(executor, value)
222
- script = value.keys.map { |k| JS_SET_TRANSFORM_VALUE % { key: k, value: value[k] } }.join('; ')
263
+ script = value.keys.map do |k|
264
+ JS_SET_TRANSFORM_VALUE % { element: 'document.documentElement', key: k, value: value[k] }
265
+ end.join('; ')
223
266
  executor.execute_script(script)
224
267
  end
225
268
 
269
+ def set_element_transforms(executor, element, transform)
270
+ value = {}
271
+ JS_TRANSFORM_KEYS.map { |tk| value[tk] = transform }
272
+ script = value.keys.map do |k|
273
+ JS_SET_TRANSFORM_VALUE % { element: 'arguments[0]', key: k, value: value[k] }
274
+ end.join('; ')
275
+ executor.execute_script(script, element)
276
+ end
277
+
278
+ def current_element_transforms(executor, element)
279
+ transform_script = JS_TRANSFORM_KEYS.map do |tk|
280
+ "'#{tk}': #{JS_GET_TRANSFORM_VALUE % { element: 'arguments[0]', key: tk }}"
281
+ end.join(', ')
282
+ script = "return { #{transform_script} };"
283
+ executor.execute_script(script, element)
284
+ end
285
+
226
286
  def translate_to(executor, location)
227
- set_current_transforms(executor, "translate(-#{location.x}px, -#{location.y}px)")
287
+ set_current_transforms(executor, "translate(#{-location.x}px, #{-location.y}px)")
288
+ end
289
+
290
+ def element_translate_to(executor, element, location)
291
+ set_element_transforms(executor, element, "translate(#{location.x}px, #{location.y}px)")
228
292
  end
229
293
 
230
294
  # @param [Applitools::Selenium::Driver] executor
@@ -334,12 +398,24 @@ module Applitools::Utils
334
398
  end
335
399
 
336
400
  def set_browser_size_by_viewport_size(executor, actual_viewport_size, required_size)
337
- browser_size = Applitools::RectangleSize.from_any_argument(executor.manage.window.size)
401
+ browser_size = executor.manage.window.size
402
+ if browser_size.width.nil? || browser_size.height.nil?
403
+ raise(
404
+ Applitools::EyesError,
405
+ 'driver.manage.window.size returned nil values. ' \
406
+ 'Please ensure that you use the latest version of browser and its driver!'
407
+ )
408
+ end
409
+ browser_size = Applitools::RectangleSize.from_any_argument(browser_size)
338
410
  Applitools::EyesLogger.info "Current browser size: #{browser_size}"
339
411
  required_browser_size = browser_size + required_size - actual_viewport_size
340
412
  set_browser_size(executor, required_browser_size)
341
413
  end
342
414
 
415
+ def scroll_to_bottom_right(executor)
416
+ executor.execute_script(JS_SCROLL_TO_BOTTOM_RIGHT)
417
+ end
418
+
343
419
  private
344
420
 
345
421
  def with_timeout(timeout, &_block)