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.
- checksums.yaml +4 -4
- data/.gitignore +0 -2
- data/.travis.yml +16 -0
- data/Gemfile +1 -1
- data/README.md +14 -4
- data/Rakefile +8 -1
- data/eyes_selenium.gemspec +26 -17
- data/lib/applitools/base/batch_info.rb +19 -0
- data/lib/applitools/base/dimension.rb +21 -0
- data/lib/applitools/base/environment.rb +19 -0
- data/lib/applitools/base/mouse_trigger.rb +33 -0
- data/lib/applitools/base/point.rb +21 -0
- data/lib/applitools/base/region.rb +77 -0
- data/lib/applitools/base/server_connector.rb +113 -0
- data/lib/applitools/base/session.rb +15 -0
- data/lib/applitools/base/start_info.rb +34 -0
- data/lib/applitools/base/test_results.rb +36 -0
- data/lib/applitools/base/text_trigger.rb +22 -0
- data/lib/applitools/eyes.rb +393 -0
- data/lib/applitools/eyes_logger.rb +40 -0
- data/lib/applitools/method_tracer.rb +22 -0
- data/lib/applitools/selenium/driver.rb +194 -0
- data/lib/applitools/selenium/element.rb +66 -0
- data/lib/applitools/selenium/keyboard.rb +27 -0
- data/lib/applitools/selenium/match_window_data.rb +24 -0
- data/lib/applitools/selenium/match_window_task.rb +190 -0
- data/lib/applitools/selenium/mouse.rb +62 -0
- data/lib/applitools/selenium/viewport_size.rb +128 -0
- data/lib/applitools/utils/image_delta_compressor.rb +150 -0
- data/lib/applitools/utils/image_utils.rb +63 -0
- data/lib/applitools/utils/utils.rb +52 -0
- data/lib/applitools/version.rb +3 -0
- data/lib/eyes_selenium.rb +9 -29
- data/spec/driver_passthrough_spec.rb +25 -25
- data/spec/spec_helper.rb +5 -8
- data/test/appium_example_script.rb +57 -0
- data/{test_script.rb → test/test_script.rb} +7 -9
- data/{watir_test.rb → test/watir_test_script.rb} +6 -4
- metadata +120 -48
- data/appium_eyes_example.rb +0 -56
- data/lib/eyes_selenium/capybara.rb +0 -21
- data/lib/eyes_selenium/eyes/agent_connector.rb +0 -76
- data/lib/eyes_selenium/eyes/batch_info.rb +0 -19
- data/lib/eyes_selenium/eyes/dimension.rb +0 -15
- data/lib/eyes_selenium/eyes/driver.rb +0 -266
- data/lib/eyes_selenium/eyes/element.rb +0 -78
- data/lib/eyes_selenium/eyes/environment.rb +0 -15
- data/lib/eyes_selenium/eyes/eyes.rb +0 -396
- data/lib/eyes_selenium/eyes/eyes_keyboard.rb +0 -25
- data/lib/eyes_selenium/eyes/eyes_mouse.rb +0 -60
- data/lib/eyes_selenium/eyes/failure_reports.rb +0 -4
- data/lib/eyes_selenium/eyes/match_level.rb +0 -8
- data/lib/eyes_selenium/eyes/match_window_data.rb +0 -18
- data/lib/eyes_selenium/eyes/match_window_task.rb +0 -182
- data/lib/eyes_selenium/eyes/mouse_trigger.rb +0 -23
- data/lib/eyes_selenium/eyes/region.rb +0 -72
- data/lib/eyes_selenium/eyes/screenshot_taker.rb +0 -18
- data/lib/eyes_selenium/eyes/session.rb +0 -14
- data/lib/eyes_selenium/eyes/start_info.rb +0 -32
- data/lib/eyes_selenium/eyes/test_results.rb +0 -32
- data/lib/eyes_selenium/eyes/text_trigger.rb +0 -19
- data/lib/eyes_selenium/eyes/viewport_size.rb +0 -105
- data/lib/eyes_selenium/eyes_logger.rb +0 -47
- data/lib/eyes_selenium/utils.rb +0 -6
- data/lib/eyes_selenium/utils/image_delta_compressor.rb +0 -149
- data/lib/eyes_selenium/utils/image_utils.rb +0 -76
- data/lib/eyes_selenium/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47b395b9cd5931cd1cdf51770296824d4123540e
|
4
|
+
data.tar.gz: ed4cfaadc2824b1140d64abee6322e08a5a99e94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7f9f968f8be5d0108c768084e00213a575b946abdad64de5b389008439f8ffcc2ab24892ddf68f43229ba4d51202bb9ec509b478e87f94640ce7d108f7a09f6
|
7
|
+
data.tar.gz: 5fa006f0a50e22a1e9e2e31a17b31d25c47f11f90e98f1ecb70c051473fb998561bb1ec2b0031cdb859fc651077de559c086d2e4374d12d08df540f49cc9d325
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
@@ -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
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
# Applitools
|
1
|
+
# Applitools
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/eyes_selenium)
|
4
|
+
[](https://travis-ci.org/applitools/Eyes.Selenium.Ruby)
|
5
|
+
[](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
|
-
|
13
|
+
```ruby
|
14
|
+
gem 'eyes_selenium'
|
15
|
+
```
|
10
16
|
|
11
17
|
And then execute:
|
12
18
|
|
13
|
-
|
19
|
+
```ruby
|
20
|
+
$ bundle
|
21
|
+
```
|
14
22
|
|
15
23
|
Or install it yourself as:
|
16
24
|
|
17
|
-
|
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
data/eyes_selenium.gemspec
CHANGED
@@ -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 '
|
4
|
+
require 'applitools/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'eyes_selenium'
|
8
8
|
spec.version = Applitools::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
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 = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_dependency
|
23
|
-
spec.add_dependency
|
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
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
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,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
|