eyes_selenium 2.16.0 → 2.17.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 47b395b9cd5931cd1cdf51770296824d4123540e
4
- data.tar.gz: ed4cfaadc2824b1140d64abee6322e08a5a99e94
3
+ metadata.gz: 250fb34d1762517235653022b1912a310f725030
4
+ data.tar.gz: e72d68a5d5927ad9bf4deaef8375820cc5c8fe23
5
5
  SHA512:
6
- metadata.gz: a7f9f968f8be5d0108c768084e00213a575b946abdad64de5b389008439f8ffcc2ab24892ddf68f43229ba4d51202bb9ec509b478e87f94640ce7d108f7a09f6
7
- data.tar.gz: 5fa006f0a50e22a1e9e2e31a17b31d25c47f11f90e98f1ecb70c051473fb998561bb1ec2b0031cdb859fc651077de559c086d2e4374d12d08df540f49cc9d325
6
+ metadata.gz: 9e86ee6df164195fd10b9b66032ca7132fd53deadca423ce904672e553b76e92f55c8f99f195d90bcf5217ebecf695a01aa86c5d62afa4cd6f9559e7cfa7b436
7
+ data.tar.gz: 41c97cde1b72b9dee573fec079fc80f6a3823c1ea00e41e45778a48743c10fe7292222d2a4a77a761f5dbe9dcdcc659dcc3de3fedc857496a4f47bdfc0d7d6ce
data/.rubocop.yml ADDED
@@ -0,0 +1,54 @@
1
+ # Custom config for RuboCop static code analysis
2
+ Metrics/LineLength:
3
+ Max: 120
4
+
5
+ Metrics/MethodLength:
6
+ Enabled: false
7
+
8
+ Metrics/ClassLength:
9
+ Enabled: false
10
+
11
+ Metrics/ParameterLists:
12
+ Enabled: false
13
+
14
+ Metrics/CyclomaticComplexity:
15
+ Enabled: false
16
+
17
+ Metrics/PerceivedComplexity:
18
+ Enabled: false
19
+
20
+ Metrics/AbcSize:
21
+ Enabled: false
22
+
23
+ Metrics/BlockNesting:
24
+ Max: 4
25
+
26
+ Style/SignalException:
27
+ EnforcedStyle: only_raise
28
+
29
+ Style/RaiseArgs:
30
+ Enabled: false
31
+
32
+ Style/AlignParameters:
33
+ EnforcedStyle: with_fixed_indentation
34
+
35
+ Style/HashSyntax:
36
+ UseHashRocketsWithSymbolValues: true
37
+
38
+ Style/AlignHash:
39
+ Enabled: false
40
+
41
+ Style/MultilineOperationIndentation:
42
+ EnforcedStyle: indented
43
+
44
+ Style/IndentHash:
45
+ EnforcedStyle: consistent
46
+
47
+ Style/ClassAndModuleChildren:
48
+ Enabled: false
49
+
50
+ Style/Documentation:
51
+ Enabled: false
52
+
53
+ Style/ModuleFunction:
54
+ Enabled: false
data/.travis.yml CHANGED
@@ -14,3 +14,5 @@ sudo: false
14
14
  before_install:
15
15
  - "export DISPLAY=:99.0"
16
16
  - "sh -e /etc/init.d/xvfb start"
17
+ script:
18
+ - bundle exec rake rubocop
data/Rakefile CHANGED
@@ -1,8 +1,11 @@
1
1
  #!/usr/bin/env rake
2
2
  require 'bundler/gem_tasks'
3
3
  require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
4
5
 
5
6
  RSpec::Core::RakeTask.new('spec')
6
7
  Bundler::GemHelper.install_tasks
7
8
 
8
9
  task :default => :spec
10
+
11
+ RuboCop::RakeTask.new
@@ -13,13 +13,13 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'https://www.applitools.com'
14
14
  spec.license = 'Apache License, Version 2.0'
15
15
 
16
- spec.files = `git ls-files`.split($/)
16
+ spec.files = `git ls-files`.split($RS)
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'selenium-webdriver', '>= 2.45.0'
22
- spec.add_dependency 'oily_png'
22
+ spec.add_dependency 'oily_png', '>= 1.2'
23
23
  spec.add_dependency 'faraday'
24
24
  spec.add_dependency 'oj'
25
25
 
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency 'rspec', '>= 3'
29
29
  spec.add_development_dependency 'watir-webdriver'
30
30
  spec.add_development_dependency 'appium_lib'
31
+ spec.add_development_dependency 'rubocop'
31
32
 
32
33
  # Exclude debugging support on Travis CI, due to its incompatibility with jruby and older rubies.
33
34
  unless ENV['TRAVIS']
@@ -0,0 +1,10 @@
1
+ module Applitools::Base
2
+ class ImagePosition
3
+ attr_accessor :image, :position
4
+
5
+ def initialize(image, position)
6
+ @image = image
7
+ @position = position
8
+ end
9
+ end
10
+ end
@@ -7,7 +7,7 @@ module Applitools::Base
7
7
  move: 'Move',
8
8
  down: 'Down',
9
9
  up: 'Up'
10
- }.freeze
10
+ }.freeze
11
11
 
12
12
  attr_reader :mouse_action, :control, :location
13
13
 
@@ -2,16 +2,29 @@ module Applitools::Base
2
2
  class Point
3
3
  attr_accessor :x, :y
4
4
 
5
+ alias_attribute :left, :x
6
+ alias_attribute :top, :y
7
+
5
8
  def initialize(x, y)
6
9
  @x = x
7
10
  @y = y
8
11
  end
9
12
 
10
- def to_hash
11
- {
12
- x: x,
13
- y: y
14
- }
13
+ TOP_LEFT = Point.new(0, 0)
14
+
15
+ def ==(other)
16
+ return super.==(other) unless other.is_a?(Point)
17
+ @x == other.x && @y == other.y
18
+ end
19
+
20
+ def hash
21
+ @x.hash & @y.hash
22
+ end
23
+
24
+ alias_method :eql?, :==
25
+
26
+ def to_hash(options = {})
27
+ options[:region] ? { left: left, top: top } : { x: x, y: y }
15
28
  end
16
29
 
17
30
  def values
@@ -9,7 +9,7 @@ module Applitools::Base
9
9
  @height = height.round
10
10
  end
11
11
 
12
- EMPTY = Applitools::Base::Region.new(0, 0, 0, 0)
12
+ EMPTY = Region.new(0, 0, 0, 0)
13
13
 
14
14
  def make_empty
15
15
  @left = EMPTY.left
@@ -19,7 +19,7 @@ module Applitools::Base
19
19
  end
20
20
 
21
21
  def empty?
22
- @left == EMPTY.left && @top == EMPTY.top && @width == EMPTY.width && @height == EMPTY.height
22
+ @left == EMPTY.left && @top == EMPTY.top && @width == EMPTY.width && @height == EMPTY.height
23
23
  end
24
24
 
25
25
  def right
@@ -31,14 +31,17 @@ module Applitools::Base
31
31
  end
32
32
 
33
33
  def intersecting?(other)
34
- ((left <= other.left && other.left <= right) || (other.left <= left && left <= other.right)) \
35
- && ((top <= other.top && other.top <= bottom) || (other.top <= top && top <=other.bottom))
34
+ ((left <= other.left && other.left <= right) || (other.left <= left && left <= other.right)) &&
35
+ ((top <= other.top && other.top <= bottom) || (other.top <= top && top <= other.bottom))
36
36
  end
37
37
 
38
38
  def intersect(other)
39
- if !intersecting?(other)
40
- make_empty and return
39
+ unless intersecting?(other)
40
+ make_empty
41
+
42
+ return
41
43
  end
44
+
42
45
  i_left = (left >= other.left) ? left : other.left
43
46
  i_right = (right <= other.right) ? right : other.right
44
47
  i_top = (top >= other.top) ? top : other.top
@@ -51,14 +54,46 @@ module Applitools::Base
51
54
  end
52
55
 
53
56
  def contains?(other_left, other_top)
54
- other_left >= left && other_left <= right && \
55
- other_top >= top && other_top <= bottom
57
+ other_left >= left && other_left <= right && other_top >= top && other_top <= bottom
56
58
  end
57
59
 
58
60
  def middle_offset
59
61
  mid_x = width / 2
60
62
  mid_y = height / 2
61
- Applitools::Base::Point.new(mid_x.round, mid_y.round)
63
+ Point.new(mid_x.round, mid_y.round)
64
+ end
65
+
66
+ def subregions(subregion_size)
67
+ [].tap do |subregions|
68
+ current_top = @top
69
+ bottom = @top + @height
70
+ right = @left + @width
71
+ subregion_width = [@width, subregion_size.width].min
72
+ subregion_height = [@height, subregion_size.height].min
73
+
74
+ while current_top < bottom
75
+ current_bottom = current_top + subregion_height
76
+ if current_bottom > bottom
77
+ current_bottom = bottom
78
+ current_top = current_bottom - subregion_height
79
+ end
80
+
81
+ current_left = @left
82
+ while current_left < right
83
+ current_right = current_left + subregion_width
84
+ if current_right > right
85
+ current_right = right
86
+ current_left = current_right - subregion_width
87
+ end
88
+
89
+ subregions << Region.new(current_left, current_top, subregion_width, subregion_height)
90
+
91
+ current_left += subregion_width
92
+ end
93
+
94
+ current_top += subregion_height
95
+ end
96
+ end
62
97
  end
63
98
 
64
99
  def to_hash
@@ -1,7 +1,7 @@
1
1
  require 'faraday'
2
2
 
3
3
  require 'oj'
4
- Oj.default_options = {:mode => :compat }
4
+ Oj.default_options = { :mode => :compat }
5
5
 
6
6
  require 'uri'
7
7
 
@@ -44,7 +44,8 @@ module Applitools::Base::ServerConnector
44
44
  end
45
45
 
46
46
  def start_session(session_start_info)
47
- res = post(endpoint_url, body: Oj.dump(startInfo: Applitools::Utils.camelcase_hash_keys(session_start_info.to_hash)))
47
+ res = post(endpoint_url, body: Oj.dump(startInfo:
48
+ Applitools::Utils.camelcase_hash_keys(session_start_info.to_hash)))
48
49
  raise Applitools::EyesError.new("Request failed: #{res.status}") unless res.success?
49
50
 
50
51
  response = Oj.load(res.body)
@@ -52,7 +53,7 @@ module Applitools::Base::ServerConnector
52
53
  end
53
54
 
54
55
  def stop_session(session, aborted = nil, save = false)
55
- res = long_delete(URI.join(endpoint_url, session.id.to_s), query: {aborted: aborted, updateBaseline: save})
56
+ res = long_delete(URI.join(endpoint_url, session.id.to_s), query: { aborted: aborted, updateBaseline: save })
56
57
  raise Applitools::EyesError.new("Request failed: #{res.status}") unless res.success?
57
58
 
58
59
  response = Oj.load(res.body)
@@ -82,11 +83,11 @@ module Applitools::Base::ServerConnector
82
83
  end
83
84
 
84
85
  def request(url, method, options = {})
85
- Faraday::Connection.new(url, ssl: {ca_file: SSL_CERT}).send(method) do |req|
86
+ Faraday::Connection.new(url, ssl: { ca_file: SSL_CERT }).send(method) do |req|
86
87
  req.options.timeout = DEFAULT_TIMEOUT
87
88
  req.headers = DEFAULT_HEADERS.merge(options[:headers] || {})
88
89
  req.headers['Content-Type'] = options[:content_type] if options.key?(:content_type)
89
- req.params = {apiKey: api_key}.merge(options[:query] || {})
90
+ req.params = { apiKey: api_key }.merge(options[:query] || {})
90
91
  req.body = options[:body]
91
92
  end
92
93
  end
@@ -95,7 +96,7 @@ module Applitools::Base::ServerConnector
95
96
  delay = LONG_REQUEST_DELAY
96
97
  (options[:headers] ||= {})['Eyes-Expect'] = '202-accepted'
97
98
 
98
- while true
99
+ loop do
99
100
  # Date should be in RFC 1123 format.
100
101
  options[:headers]['Eyes-Date'] = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
101
102
 
@@ -2,7 +2,7 @@ module Applitools::Base
2
2
  class TestResults
3
3
  attr_accessor :is_new, :url
4
4
  attr_reader :steps, :matches, :mismatches, :missing, :exact_matches, :strict_matches, :content_matches,
5
- :layout_matches, :none_matches, :is_passed
5
+ :layout_matches, :none_matches
6
6
 
7
7
  def initialize(steps = 0, matches = 0, mismatches = 0, missing = 0, exact_matches = 0, strict_matches = 0,
8
8
  content_matches = 0, layout_matches = 0, none_matches = 0)
@@ -19,15 +19,14 @@ module Applitools::Base
19
19
  @url = nil
20
20
  end
21
21
 
22
- def is_passed
22
+ def passed?
23
23
  !is_new && mismatches == 0 && missing == 0
24
24
  end
25
+ alias_method :is_passed, :passed?
25
26
 
26
27
  def to_s
27
28
  is_new_str = ''
28
- unless is_new.nil?
29
- is_new_str = is_new ? 'New test' : 'Existing test'
30
- end
29
+ is_new_str = is_new ? 'New test' : 'Existing test' unless is_new.nil?
31
30
 
32
31
  "#{is_new_str} [ steps: #{steps}, matches: #{matches}, mismatches: #{mismatches}, missing: #{missing} ], "\
33
32
  "URL: #{url}"
@@ -0,0 +1,17 @@
1
+ class Module
2
+ def alias_attribute(new_name, old_name)
3
+ module_eval <<-STR, __FILE__, __LINE__ + 1
4
+ def #{new_name}
5
+ self.#{old_name}
6
+ end
7
+
8
+ def #{new_name}?
9
+ self.#{old_name}?
10
+ end
11
+
12
+ def #{new_name}=(v)
13
+ self.#{old_name}
14
+ end
15
+ STR
16
+ end
17
+ end
@@ -23,7 +23,9 @@ class Applitools::Eyes
23
23
  DEFAULT_MATCH_TIMEOUT = 2.0.freeze # Seconds
24
24
  BASE_AGENT_ID = ('eyes.selenium.ruby/' + Applitools::VERSION).freeze
25
25
 
26
- #
26
+ ANDROID = 'Android'.freeze
27
+ IOS = 'iOS'.freeze
28
+
27
29
  # Attributes:
28
30
  #
29
31
  # +app_name+:: +String+ The application name which was provided as an argument to +open+.
@@ -31,7 +33,8 @@ class Applitools::Eyes
31
33
  # +is_open+:: +boolean+ Is there an open session.
32
34
  # +viewport_size+:: +Hash+ The viewport size which was provided as an argument to +open+. Should include +width+
33
35
  # and +height+.
34
- # +driver+:: +Applitools::Selenium::Driver+ The driver instance wrapping the driver which was provided as an argument to +open+.
36
+ # +driver+:: +Applitools::Selenium::Driver+ The driver instance wrapping the driver which was provided as an argument
37
+ # to +open+.
35
38
  # +api_key+:: +String+ The user's API key.
36
39
  # +match_timeout+:: +Float+ The default timeout for check_XXXX operations. (Seconds)
37
40
  # +batch+:: +BatchInfo+ The current tests grouping, if any.
@@ -41,8 +44,8 @@ class Applitools::Eyes
41
44
  # you wish to override Eyes' automatic inference.
42
45
  # +branch_name+:: +String+ If set, names the branch in which the test should run.
43
46
  # +parent_branch_name+:: +String+ If set, names the parent branch of the branch in which the test should run.
44
- # +user_inputs+:: +Applitools::Base::MouseTrigger+/+Applitools::Selenium::KeyboardTrigger+ Mouse/Keyboard events which happened after
45
- # the last visual validation.
47
+ # +user_inputs+:: +Applitools::Base::MouseTrigger+/+Applitools::Selenium::KeyboardTrigger+ Mouse/Keyboard events which
48
+ # happened after the last visual validation.
46
49
  # +save_new_tests+:: +boolean+ Whether or not new tests should be automatically accepted as baseline.
47
50
  # +save_failed_tests+:: +boolean+ Whether or not failed tests should be automatically accepted as baseline.
48
51
  # +match_level+:: +String+ The default match level for the entire session. See +Applitools::Eyes::MATCH_LEVEL+.
@@ -58,10 +61,14 @@ class Applitools::Eyes
58
61
  # +rotation+:: +Integer+|+nil+ The degrees by which to rotate the screenshots received from the driver. Set this to
59
62
  # override Eyes' automatic rotation inference. Positive values = clockwise rotation, negative
60
63
  # values = counter-clockwise, 0 = force no rotation, +nil+ = use Eyes' automatic rotation inference.
64
+ # +force_fullpage_screenshot+:: +boolean+ Whether or not to force fullpage screenshot taking, if the browser doesn't
65
+ # support it explicitly.
66
+ # +hide_scrollbars+:: +boolean+ Whether or not hide scrollbars.
67
+ # +use_css_transition+:: +boolean+ Whether or not to perform CSS transition.
61
68
  attr_reader :app_name, :test_name, :is_open, :viewport_size, :driver
62
69
  attr_accessor :match_timeout, :batch, :host_os, :host_app, :branch_name, :parent_branch_name, :user_inputs,
63
70
  :save_new_tests, :save_failed_tests, :is_disabled, :server_url, :agent_id, :failure_reports, :match_level,
64
- :baseline_name, :rotation
71
+ :baseline_name, :rotation, :force_fullpage_screenshot, :hide_scrollbars, :use_css_transition
65
72
 
66
73
  def_delegators 'Applitools::EyesLogger', :log_handler, :log_handler=
67
74
  def_delegators 'Applitools::Base::ServerConnector', :api_key, :api_key=, :server_url, :server_url=
@@ -98,6 +105,9 @@ class Applitools::Eyes
98
105
  @save_new_tests = true
99
106
  @save_failed_tests = false
100
107
  @dont_get_title = false
108
+ @force_fullpage_screenshot = false
109
+ @hide_scrollbars = false
110
+ @use_css_transition = false
101
111
  end
102
112
 
103
113
  def open(options = {})
@@ -105,7 +115,7 @@ class Applitools::Eyes
105
115
  return driver if disabled?
106
116
 
107
117
  if api_key.nil?
108
- raise Applitools::EyesError.new("API key not set! Log in to https://applitools.com to obtain your API Key and "\
118
+ raise Applitools::EyesError.new('API key not set! Log in to https://applitools.com to obtain your API Key and '\
109
119
  "use 'api_key' to set it.")
110
120
  end
111
121
 
@@ -180,7 +190,7 @@ class Applitools::Eyes
180
190
  check_region_(Applitools::Base::Region::EMPTY, tag, specific_timeout)
181
191
  end
182
192
 
183
- def close(raise_ex=true)
193
+ def close(raise_ex = true)
184
194
  return if disabled?
185
195
  @is_open = false
186
196
 
@@ -217,7 +227,7 @@ class Applitools::Eyes
217
227
  return results
218
228
  end
219
229
 
220
- unless results.is_passed
230
+ unless results.passed?
221
231
  # Test failed
222
232
  Applitools::EyesLogger.info "--- Failed test ended. See details at #{session_results_url}"
223
233
 
@@ -246,15 +256,13 @@ class Applitools::Eyes
246
256
  # get "http://www.google.com"
247
257
  # check_window("initial")
248
258
  # end
249
- #noinspection RubyUnusedLocalVariable
250
- def test(options = {}, &block)
251
- begin
252
- open(options)
253
- yield(driver)
254
- close
255
- ensure
256
- abort_if_not_closed
257
- end
259
+ # noinspection RubyUnusedLocalVariable
260
+ def test(options = {}, &_block)
261
+ open(options)
262
+ yield(driver)
263
+ close
264
+ ensure
265
+ abort_if_not_closed
258
266
  end
259
267
 
260
268
  def abort_if_not_closed
@@ -266,7 +274,7 @@ class Applitools::Eyes
266
274
 
267
275
  begin
268
276
  Applitools::Base::ServerConnector.stop_session(@session, true, false)
269
- rescue Exception, Applitools::EyesError => e
277
+ rescue => e
270
278
  Applitools::EyesLogger.error "Failed to abort server session: #{e.message}!"
271
279
  ensure
272
280
  @session = nil
@@ -280,8 +288,8 @@ class Applitools::Eyes
280
288
  end
281
289
 
282
290
  def get_driver(options)
283
- # TODO remove the "browser" related block when possible. It's for backward compatibility.
284
- if options.has_key?(:browser)
291
+ # TODO: remove the "browser" related block when possible. It's for backward compatibility.
292
+ if options.key?(:browser)
285
293
  Applitools::EyesLogger.warn('"browser" key is deprecated, please use "driver" instead.')
286
294
 
287
295
  return options[:browser]
@@ -308,10 +316,10 @@ class Applitools::Eyes
308
316
  Applitools::EyesLogger.info 'Mobile device detected! Checking device type..'
309
317
  if driver.android?
310
318
  Applitools::EyesLogger.info 'Android detected.'
311
- platform_name = 'Android'
319
+ platform_name = ANDROID
312
320
  elsif driver.ios?
313
321
  Applitools::EyesLogger.info 'iOS detected.'
314
- platform_name = 'iOS'
322
+ platform_name = IOS
315
323
  else
316
324
  Applitools::EyesLogger.warn 'Unknown device type.'
317
325
  end
@@ -379,15 +387,15 @@ class Applitools::Eyes
379
387
  as_expected = @match_window_task.match_window(region, specific_timeout, tag, rotation,
380
388
  @should_match_window_run_once_on_timeout)
381
389
  Applitools::EyesLogger.debug 'Match window done!'
382
- unless as_expected
383
- @should_match_window_run_once_on_timeout = true
384
- unless @session.new_session?
385
- Applitools::EyesLogger.info %( mismatch #{ tag ? '' : "(#{tag})" } )
386
- if failure_reports.to_i == Applitools::Eyes::FAILURE_REPORTS[:immediate]
387
- raise Applitools::TestFailedError.new("Mismatch found in '#{@session_start_info.scenario_id_or_name}' "\
388
- "of '#{@session_start_info.app_id_or_name}'")
389
- end
390
- end
391
- end
390
+ return if as_expected
391
+
392
+ @should_match_window_run_once_on_timeout = true
393
+ return if @session.new_session?
394
+
395
+ Applitools::EyesLogger.info %( mismatch #{ tag ? '' : "(#{tag})" } )
396
+ return unless failure_reports.to_i == Applitools::Eyes::FAILURE_REPORTS[:immediate]
397
+
398
+ raise Applitools::TestFailedError.new("Mismatch found in '#{@session_start_info.scenario_id_or_name}' "\
399
+ "of '#{@session_start_info.app_id_or_name}'")
392
400
  end
393
401
  end