eyes_selenium 2.15.0 → 2.16.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.travis.yml +16 -0
  4. data/Gemfile +1 -1
  5. data/README.md +14 -4
  6. data/Rakefile +8 -1
  7. data/eyes_selenium.gemspec +26 -17
  8. data/lib/applitools/base/batch_info.rb +19 -0
  9. data/lib/applitools/base/dimension.rb +21 -0
  10. data/lib/applitools/base/environment.rb +19 -0
  11. data/lib/applitools/base/mouse_trigger.rb +33 -0
  12. data/lib/applitools/base/point.rb +21 -0
  13. data/lib/applitools/base/region.rb +77 -0
  14. data/lib/applitools/base/server_connector.rb +113 -0
  15. data/lib/applitools/base/session.rb +15 -0
  16. data/lib/applitools/base/start_info.rb +34 -0
  17. data/lib/applitools/base/test_results.rb +36 -0
  18. data/lib/applitools/base/text_trigger.rb +22 -0
  19. data/lib/applitools/eyes.rb +393 -0
  20. data/lib/applitools/eyes_logger.rb +40 -0
  21. data/lib/applitools/method_tracer.rb +22 -0
  22. data/lib/applitools/selenium/driver.rb +194 -0
  23. data/lib/applitools/selenium/element.rb +66 -0
  24. data/lib/applitools/selenium/keyboard.rb +27 -0
  25. data/lib/applitools/selenium/match_window_data.rb +24 -0
  26. data/lib/applitools/selenium/match_window_task.rb +190 -0
  27. data/lib/applitools/selenium/mouse.rb +62 -0
  28. data/lib/applitools/selenium/viewport_size.rb +128 -0
  29. data/lib/applitools/utils/image_delta_compressor.rb +150 -0
  30. data/lib/applitools/utils/image_utils.rb +63 -0
  31. data/lib/applitools/utils/utils.rb +52 -0
  32. data/lib/applitools/version.rb +3 -0
  33. data/lib/eyes_selenium.rb +9 -29
  34. data/spec/driver_passthrough_spec.rb +25 -25
  35. data/spec/spec_helper.rb +5 -8
  36. data/test/appium_example_script.rb +57 -0
  37. data/{test_script.rb → test/test_script.rb} +7 -9
  38. data/{watir_test.rb → test/watir_test_script.rb} +6 -4
  39. metadata +120 -48
  40. data/appium_eyes_example.rb +0 -56
  41. data/lib/eyes_selenium/capybara.rb +0 -21
  42. data/lib/eyes_selenium/eyes/agent_connector.rb +0 -76
  43. data/lib/eyes_selenium/eyes/batch_info.rb +0 -19
  44. data/lib/eyes_selenium/eyes/dimension.rb +0 -15
  45. data/lib/eyes_selenium/eyes/driver.rb +0 -266
  46. data/lib/eyes_selenium/eyes/element.rb +0 -78
  47. data/lib/eyes_selenium/eyes/environment.rb +0 -15
  48. data/lib/eyes_selenium/eyes/eyes.rb +0 -396
  49. data/lib/eyes_selenium/eyes/eyes_keyboard.rb +0 -25
  50. data/lib/eyes_selenium/eyes/eyes_mouse.rb +0 -60
  51. data/lib/eyes_selenium/eyes/failure_reports.rb +0 -4
  52. data/lib/eyes_selenium/eyes/match_level.rb +0 -8
  53. data/lib/eyes_selenium/eyes/match_window_data.rb +0 -18
  54. data/lib/eyes_selenium/eyes/match_window_task.rb +0 -182
  55. data/lib/eyes_selenium/eyes/mouse_trigger.rb +0 -23
  56. data/lib/eyes_selenium/eyes/region.rb +0 -72
  57. data/lib/eyes_selenium/eyes/screenshot_taker.rb +0 -18
  58. data/lib/eyes_selenium/eyes/session.rb +0 -14
  59. data/lib/eyes_selenium/eyes/start_info.rb +0 -32
  60. data/lib/eyes_selenium/eyes/test_results.rb +0 -32
  61. data/lib/eyes_selenium/eyes/text_trigger.rb +0 -19
  62. data/lib/eyes_selenium/eyes/viewport_size.rb +0 -105
  63. data/lib/eyes_selenium/eyes_logger.rb +0 -47
  64. data/lib/eyes_selenium/utils.rb +0 -6
  65. data/lib/eyes_selenium/utils/image_delta_compressor.rb +0 -149
  66. data/lib/eyes_selenium/utils/image_utils.rb +0 -76
  67. data/lib/eyes_selenium/version.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e5d8d5bd76a819da52f7fc72a1c81a923c9f9a97
4
- data.tar.gz: 1330ef8e52a1a9e0c772c6000dcb55303f8fc86c
3
+ metadata.gz: 47b395b9cd5931cd1cdf51770296824d4123540e
4
+ data.tar.gz: ed4cfaadc2824b1140d64abee6322e08a5a99e94
5
5
  SHA512:
6
- metadata.gz: c587d0a9605ca5547e0b17b561a4b243a25ffa4d1ec7d72f2b8de1fece7d7c576f5262122854d15581ec793439c75188d4132fa91eaa89537e38ec8604bd236d
7
- data.tar.gz: 5f9fbb8dbab7175f7cadaec99bc119a98772c5b56000015a347713a4b2dbfde93e09c786fab71bb6c06eac0cdacb5f52ed505959b3dda3d3f23e4060d6bc5094
6
+ metadata.gz: a7f9f968f8be5d0108c768084e00213a575b946abdad64de5b389008439f8ffcc2ab24892ddf68f43229ba4d51202bb9ec509b478e87f94640ce7d108f7a09f6
7
+ data.tar.gz: 5fa006f0a50e22a1e9e2e31a17b31d25c47f11f90e98f1ecb70c051473fb998561bb1ec2b0031cdb859fc651077de559c086d2e4374d12d08df540f49cc9d325
data/.gitignore CHANGED
@@ -15,6 +15,4 @@ rdoc
15
15
  .idea/
16
16
  .idea-*/
17
17
  spec/reports
18
- test/tmp
19
- test/version_tmp
20
18
  tmp
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.6
6
+ - 2.2.2
7
+ - ruby-head
8
+ - rbx-2
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: rbx-2
12
+ # Use the faster container based infrastructure.
13
+ sudo: false
14
+ before_install:
15
+ - "export DISPLAY=:99.0"
16
+ - "sh -e /etc/init.d/xvfb start"
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in applitools.gemspec
3
+ # Specify your gem's dependencies in eyes_selenium.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -1,4 +1,8 @@
1
- # Applitools [![Gem Version](https://badge.fury.io/rb/eyes_selenium.svg)](https://rubygems.org/gems/eyes_selenium)
1
+ # Applitools
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/eyes_selenium.svg)](http://badge.fury.io/rb/eyes_selenium)
4
+ [![Build Status](https://travis-ci.org/applitools/Eyes.Selenium.Ruby.svg)](https://travis-ci.org/applitools/Eyes.Selenium.Ruby)
5
+ [![Dependency Status](https://gemnasium.com/applitools/Eyes.Selenium.Ruby.svg)](https://gemnasium.com/applitools/Eyes.Selenium.Ruby)
2
6
 
3
7
  Applitools Ruby SDK.
4
8
 
@@ -6,15 +10,21 @@ Applitools Ruby SDK.
6
10
 
7
11
  Add this line to your application's Gemfile:
8
12
 
9
- gem 'eyes_selenium'
13
+ ```ruby
14
+ gem 'eyes_selenium'
15
+ ```
10
16
 
11
17
  And then execute:
12
18
 
13
- $ bundle
19
+ ```ruby
20
+ $ bundle
21
+ ```
14
22
 
15
23
  Or install it yourself as:
16
24
 
17
- $ gem install eyes_selenium
25
+ ```bash
26
+ gem install eyes_selenium
27
+ ```
18
28
 
19
29
  ## Usage
20
30
  Please check the applitools website for usage instructions: http://www.applitools.com
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
- require "bundler/gem_tasks"
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new('spec')
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ task :default => :spec
@@ -1,30 +1,39 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'eyes_selenium/version'
4
+ require 'applitools/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "eyes_selenium"
7
+ spec.name = 'eyes_selenium'
8
8
  spec.version = Applitools::VERSION
9
- spec.authors = ["Applitools team"]
10
- spec.email = ["team@applitools.com"]
11
- spec.description = "Applitools Ruby SDK"
12
- spec.summary = "Applitools Ruby SDK"
13
- spec.homepage = "http://www.applitools.com"
14
- spec.license = "Apache License, Version 2.0"
9
+ spec.authors = ['Applitools Team']
10
+ spec.email = ['team@applitools.com']
11
+ spec.description = 'Applitools Ruby SDK'
12
+ spec.summary = 'Applitools Ruby SDK'
13
+ spec.homepage = 'https://www.applitools.com'
14
+ spec.license = 'Apache License, Version 2.0'
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
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
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency "selenium-webdriver", [">= 2.45.0"]
22
- spec.add_dependency "httparty"
23
- spec.add_dependency "oily_png", [">= 1.1.0"]
21
+ spec.add_dependency 'selenium-webdriver', '>= 2.45.0'
22
+ spec.add_dependency 'oily_png'
23
+ spec.add_dependency 'faraday'
24
+ spec.add_dependency 'oj'
24
25
 
25
- spec.add_development_dependency "bundler", "~> 1.3"
26
- spec.add_development_dependency "rake"
27
- spec.add_development_dependency "rspec", [">= 2.2.0"]
28
- spec.add_development_dependency "capybara", [">= 2.1.0"]
29
- spec.add_development_dependency "sinatra"
26
+ spec.add_development_dependency 'bundler'
27
+ spec.add_development_dependency 'rake'
28
+ spec.add_development_dependency 'rspec', '>= 3'
29
+ spec.add_development_dependency 'watir-webdriver'
30
+ spec.add_development_dependency 'appium_lib'
31
+
32
+ # Exclude debugging support on Travis CI, due to its incompatibility with jruby and older rubies.
33
+ unless ENV['TRAVIS']
34
+ spec.add_development_dependency 'pry'
35
+ spec.add_development_dependency 'pry-byebug'
36
+ spec.add_development_dependency 'pry-doc'
37
+ spec.add_development_dependency 'pry-stack_explorer'
38
+ end
30
39
  end
@@ -0,0 +1,19 @@
1
+ require 'securerandom'
2
+
3
+ module Applitools::Base
4
+ class BatchInfo
5
+ def initialize(name = nil, started_at = Time.now)
6
+ @name = name
7
+ @started_at = started_at
8
+ @id = SecureRandom.uuid
9
+ end
10
+
11
+ def to_hash
12
+ {
13
+ id: @id,
14
+ name: @name,
15
+ started_at: @started_at.iso8601
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Applitools::Base
2
+ class Dimension
3
+ attr_accessor :width, :height
4
+
5
+ def initialize(width, height)
6
+ @width = width
7
+ @height = height
8
+ end
9
+
10
+ def to_hash
11
+ {
12
+ width: width,
13
+ height: height
14
+ }
15
+ end
16
+
17
+ def values
18
+ [width, height]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Applitools::Base
2
+ class Environment
3
+ def initialize(os = nil, hosting_app = nil, display_size = nil, inferred = nil)
4
+ @os = os
5
+ @hosting_app = hosting_app
6
+ @display_size = display_size
7
+ @inferred = inferred
8
+ end
9
+
10
+ def to_hash
11
+ {
12
+ os: @os,
13
+ hosting_app: @hosting_app,
14
+ display_size: @display_size.to_hash,
15
+ inferred: @inferred
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,33 @@
1
+ module Applitools::Base
2
+ class MouseTrigger
3
+ MOUSE_ACTION = {
4
+ click: 'Click',
5
+ right_click: 'RightClick',
6
+ double_click: 'DoubleClick',
7
+ move: 'Move',
8
+ down: 'Down',
9
+ up: 'Up'
10
+ }.freeze
11
+
12
+ attr_reader :mouse_action, :control, :location
13
+
14
+ def initialize(mouse_action, control, location)
15
+ @mouse_action = mouse_action
16
+ @control = control
17
+ @location = location
18
+ end
19
+
20
+ def to_hash
21
+ {
22
+ trigget_type: 'Mouse',
23
+ mouse_action: MOUSE_ACTION[mouse_action],
24
+ control: control.to_hash,
25
+ location: location.to_hash
26
+ }
27
+ end
28
+
29
+ def to_s
30
+ "#{mouse_action} [#{control}] #{location.x}, #{location.y}"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ module Applitools::Base
2
+ class Point
3
+ attr_accessor :x, :y
4
+
5
+ def initialize(x, y)
6
+ @x = x
7
+ @y = y
8
+ end
9
+
10
+ def to_hash
11
+ {
12
+ x: x,
13
+ y: y
14
+ }
15
+ end
16
+
17
+ def values
18
+ [x, y]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,77 @@
1
+ module Applitools::Base
2
+ class Region
3
+ attr_accessor :left, :top, :width, :height
4
+
5
+ def initialize(left, top, width, height)
6
+ @left = left.round
7
+ @top = top.round
8
+ @width = width.round
9
+ @height = height.round
10
+ end
11
+
12
+ EMPTY = Applitools::Base::Region.new(0, 0, 0, 0)
13
+
14
+ def make_empty
15
+ @left = EMPTY.left
16
+ @top = EMPTY.top
17
+ @width = EMPTY.width
18
+ @height = EMPTY.height
19
+ end
20
+
21
+ def empty?
22
+ @left == EMPTY.left && @top == EMPTY.top && @width == EMPTY.width && @height == EMPTY.height
23
+ end
24
+
25
+ def right
26
+ left + width
27
+ end
28
+
29
+ def bottom
30
+ top + height
31
+ end
32
+
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))
36
+ end
37
+
38
+ def intersect(other)
39
+ if !intersecting?(other)
40
+ make_empty and return
41
+ end
42
+ i_left = (left >= other.left) ? left : other.left
43
+ i_right = (right <= other.right) ? right : other.right
44
+ i_top = (top >= other.top) ? top : other.top
45
+ i_bottom = (bottom <= other.bottom) ? bottom : other.bottom
46
+
47
+ @left = i_left
48
+ @top = i_top
49
+ @width = i_right - i_left
50
+ @height = i_bottom - i_top
51
+ end
52
+
53
+ def contains?(other_left, other_top)
54
+ other_left >= left && other_left <= right && \
55
+ other_top >= top && other_top <= bottom
56
+ end
57
+
58
+ def middle_offset
59
+ mid_x = width / 2
60
+ mid_y = height / 2
61
+ Applitools::Base::Point.new(mid_x.round, mid_y.round)
62
+ end
63
+
64
+ def to_hash
65
+ {
66
+ left: left,
67
+ top: top,
68
+ height: height,
69
+ width: width
70
+ }
71
+ end
72
+
73
+ def to_s
74
+ "(#{left}, #{top}), #{width} x #{height}"
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,113 @@
1
+ require 'faraday'
2
+
3
+ require 'oj'
4
+ Oj.default_options = {:mode => :compat }
5
+
6
+ require 'uri'
7
+
8
+ module Applitools::Base::ServerConnector
9
+ extend self
10
+
11
+ DEFAULT_SERVER_URL = 'https://eyessdk.applitools.com'.freeze
12
+
13
+ SSL_CERT = File.join(File.dirname(File.expand_path(__FILE__)), '../../../certs/cacert.pem').to_s.freeze
14
+ DEFAULT_TIMEOUT = 300.freeze
15
+
16
+ API_SESSIONS_RUNNING = '/api/sessions/running/'.freeze
17
+
18
+ HTTP_STATUS_CODES = {
19
+ created: 201,
20
+ accepted: 202
21
+ }.freeze
22
+
23
+ attr_accessor :server_url, :api_key
24
+ attr_reader :endpoint_url
25
+
26
+ def server_url=(url)
27
+ @server_url = url.nil? ? DEFAULT_SERVER_URL : url
28
+ @endpoint_url = URI.join(@server_url, API_SESSIONS_RUNNING).to_s
29
+ end
30
+
31
+ def match_window(session, data)
32
+ # Notice that this does not include the screenshot.
33
+ json_data = Oj.dump(Applitools::Utils.camelcase_hash_keys(data.to_hash)).force_encoding('BINARY')
34
+ body = [json_data.length].pack('L>') + json_data + data.screenshot
35
+
36
+ Applitools::EyesLogger.debug 'Sending match data...'
37
+
38
+ res = post(URI.join(endpoint_url, session.id.to_s), content_type: 'application/octet-stream', body: body)
39
+ raise Applitools::EyesError.new("Request failed: #{res.status}") unless res.success?
40
+
41
+ Oj.load(res.body)['asExpected'].tap do |as_expected|
42
+ Applitools::EyesLogger.debug "Got response! #{as_expected}"
43
+ end
44
+ end
45
+
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)))
48
+ raise Applitools::EyesError.new("Request failed: #{res.status}") unless res.success?
49
+
50
+ response = Oj.load(res.body)
51
+ Applitools::Base::Session.new(response['id'], response['url'], res.status == HTTP_STATUS_CODES[:created])
52
+ end
53
+
54
+ 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
+ raise Applitools::EyesError.new("Request failed: #{res.status}") unless res.success?
57
+
58
+ response = Oj.load(res.body)
59
+ response.delete('$id')
60
+ Applitools::Base::TestResults.new(*response.values)
61
+ end
62
+
63
+ private
64
+
65
+ DEFAULT_HEADERS = {
66
+ 'Accept' => 'application/json',
67
+ 'Content-Type' => 'application/json'
68
+ }.freeze
69
+
70
+ LONG_REQUEST_DELAY = 2.freeze # seconds
71
+ MAX_LONG_REQUEST_DELAY = 10.freeze # seconds
72
+ LONG_REQUEST_DELAY_MULTIPLICATIVE_INCREASE_FACTOR = 1.5.freeze
73
+
74
+ [:get, :post, :delete].each do |method|
75
+ define_method method do |url, options = {}|
76
+ request(url, method, options)
77
+ end
78
+
79
+ define_method "long_#{method}" do |url, options = {}|
80
+ long_request(url, method, options)
81
+ end
82
+ end
83
+
84
+ def request(url, method, options = {})
85
+ Faraday::Connection.new(url, ssl: {ca_file: SSL_CERT}).send(method) do |req|
86
+ req.options.timeout = DEFAULT_TIMEOUT
87
+ req.headers = DEFAULT_HEADERS.merge(options[:headers] || {})
88
+ req.headers['Content-Type'] = options[:content_type] if options.key?(:content_type)
89
+ req.params = {apiKey: api_key}.merge(options[:query] || {})
90
+ req.body = options[:body]
91
+ end
92
+ end
93
+
94
+ def long_request(url, method, options = {})
95
+ delay = LONG_REQUEST_DELAY
96
+ (options[:headers] ||= {})['Eyes-Expect'] = '202-accepted'
97
+
98
+ while true
99
+ # Date should be in RFC 1123 format.
100
+ options[:headers]['Eyes-Date'] = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
101
+
102
+ res = request(url, method, options)
103
+ return res unless res.status == HTTP_STATUS_CODES[:accepted]
104
+
105
+ Applitools::EyesLogger.debug "Still running... retrying in #{delay}s"
106
+ sleep delay
107
+
108
+ delay = [MAX_LONG_REQUEST_DELAY, (delay * LONG_REQUEST_DELAY_MULTIPLICATIVE_INCREASE_FACTOR).round].min
109
+ end
110
+ end
111
+
112
+ include Applitools::MethodTracer
113
+ end