eyes_images 3.0.4
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 +7 -0
- data/lib/applitools/images/eyes.rb +204 -0
- data/lib/applitools/images/eyes_images_screenshot.rb +102 -0
- data/lib/applitools/version.rb +3 -0
- data/lib/eyes_images.rb +15 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 84bf491952e354ad6a8bd5b1be3557471c590c9c
|
4
|
+
data.tar.gz: 544807f8ef98e2bdf44348a25d75fca8a7245369
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d8ff16ae3a07aa78b2a97bf018c72d1466debafd6568b68c7e9586845709cdbf395da3a73fd5a63ce3913b7042b2d884407a990e6625d9bbbb36aee8d55acfee
|
7
|
+
data.tar.gz: 3730cc602a76bf267f7e8cdcf2ca62909e5031f785d759b075b7fc4665947efd63e24e2eb94b317671733808ec44783b16134bdeb350dec8570209a75da73e28
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'applitools/core/eyes_base'
|
2
|
+
|
3
|
+
# Eyes Images SDK
|
4
|
+
#
|
5
|
+
module Applitools::Images
|
6
|
+
# A class to perform visual validation on images. Allows to handle user data like +Mouse trigger+ and +Text trigger+
|
7
|
+
# @example
|
8
|
+
# eyes = Applitools::Images::Eyes.new
|
9
|
+
# eyes.open(app_name: 'App name', test_name: 'Test name')
|
10
|
+
# eyes.check_image(eyes.check_image(image_path: '~/test/some_screenshot.png', tag: 'My Test')
|
11
|
+
# eyes.close(true)
|
12
|
+
class Eyes < Applitools::EyesBase
|
13
|
+
# @!visibility private
|
14
|
+
attr_accessor :base_agent_id, :screenshot, :inferred_environment, :title
|
15
|
+
|
16
|
+
# @!visibility private
|
17
|
+
def capture_screenshot
|
18
|
+
@screenshot
|
19
|
+
end
|
20
|
+
|
21
|
+
# Creates a new eyes object
|
22
|
+
# @example
|
23
|
+
# eyes = Applitools::Images::Eyes.new
|
24
|
+
# @param server_url The Eyes Server URL
|
25
|
+
def initialize(server_url = Applitools::Connectivity::ServerConnector::DEFAULT_SERVER_URL)
|
26
|
+
super
|
27
|
+
self.base_agent_id = 'eyes.images.ruby/1.0.0'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Starts a test.
|
31
|
+
# @param [Hash] options
|
32
|
+
# @option options [String] :app_name the name of the application under trest. Required.
|
33
|
+
# @option options [String] :test_name the test name. Required
|
34
|
+
# @option options [String | Hash] :viewport_size viewport size for the baseline, may be passed as a
|
35
|
+
# string (<tt>'800x600'</tt>) or as a hash (<tt>{width: 800, height: 600}</tt>).
|
36
|
+
# If ommited, the viewport size will be grabbed from the actual image size
|
37
|
+
# @example
|
38
|
+
# eyes.open app_name: 'my app', test_name: 'my test'
|
39
|
+
def open(options = {})
|
40
|
+
Applitools::ArgumentGuard.hash options, 'open(options)', [:app_name, :test_name]
|
41
|
+
options[:viewport_size] = Applitools::RectangleSize.from_any_argument options[:viewport_size]
|
42
|
+
open_base options
|
43
|
+
end
|
44
|
+
|
45
|
+
# Opens eyes using passed options, yields the block and then closes eyes session.
|
46
|
+
# Use Applitools::Images::Eyes method inside the block to perform the test. If the block throws an exception,
|
47
|
+
# eyes session will be closed correctly.
|
48
|
+
# @example
|
49
|
+
# eyes.test(app_name: 'Eyes.Java', test_name: 'home2') do
|
50
|
+
# eyes.check_image(image_path: './images/viber-home.png')
|
51
|
+
# eyes.check_image(image_path: './images/viber-bada.png')
|
52
|
+
# end
|
53
|
+
def test(options = {}, &_block)
|
54
|
+
open(options)
|
55
|
+
yield
|
56
|
+
close
|
57
|
+
ensure
|
58
|
+
abort_if_not_closed
|
59
|
+
end
|
60
|
+
|
61
|
+
# Matches the input image with the next expected image. Takes a hash as an argument. Returns +boolean+
|
62
|
+
# as result of matching.
|
63
|
+
# @param [Hash] options
|
64
|
+
# @option options [Applitools::Screenshot] :image
|
65
|
+
# @option options [String] :image_bytes image in PNG format. Can be obtained as ChunkyPNG::Image.to_blob()
|
66
|
+
# @option options [String] :image_path
|
67
|
+
# @option options [String] :tag An optional tag to be associated with the validation checkpoint.
|
68
|
+
# @option options [Boolean] :ignore_mismatch If set to +true+ the server should ignore a negative
|
69
|
+
# result for the visual validation. (+false+ by default)
|
70
|
+
# @example Image is a file
|
71
|
+
# eyes.check_image(image_path: '~/test/some_screenshot.png', tag: 'My Test')
|
72
|
+
# @example Image is a +Applitools::Screenshot+ instance
|
73
|
+
# eyes.check_image(image: my_image, tag: 'My Test')
|
74
|
+
# @example Image is a +String+
|
75
|
+
# eyes.check_image(image_bytes: string_represents_image, tag: 'My Test')
|
76
|
+
# @example Ignore mismatch
|
77
|
+
# eyes.check_image(image: my_image, tag: 'My Test', ignore_mismatch: true)
|
78
|
+
def check_image(options)
|
79
|
+
options = { tag: nil, ignore_mismatch: false }.merge options
|
80
|
+
|
81
|
+
if disabled?
|
82
|
+
logger.info "check_image(image, #{options[:tag]}, #{options[:ignore_mismatch]}): Ignored"
|
83
|
+
return false
|
84
|
+
end
|
85
|
+
|
86
|
+
image = get_image_from_options options
|
87
|
+
|
88
|
+
logger.info "check_image(image, #{options[:tag]}, #{options[:ignore_mismatch]})"
|
89
|
+
if image.is_a? Applitools::Screenshot
|
90
|
+
self.viewport_size = Applitools::RectangleSize.new image.width, image.height if viewport_size.nil?
|
91
|
+
self.screenshot = EyesImagesScreenshot.new image
|
92
|
+
end
|
93
|
+
self.title = options[:tag] || ''
|
94
|
+
region_provider = Object.new
|
95
|
+
region_provider.instance_eval do
|
96
|
+
define_singleton_method :region do
|
97
|
+
Applitools::Region::EMPTY
|
98
|
+
end
|
99
|
+
|
100
|
+
define_singleton_method :coordinate_type do
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
mr = check_window_base region_provider, options[:tag], options[:ignore_mismatch],
|
105
|
+
Applitools::EyesBase::USE_DEFAULT_TIMEOUT
|
106
|
+
mr.as_expected?
|
107
|
+
end
|
108
|
+
|
109
|
+
# Performs visual validation for the current image.
|
110
|
+
# @param [Hash] options
|
111
|
+
# @option options [Applitools::Region] :region A region to validate within the image
|
112
|
+
# @option options [Applitools::Screenshot] :image Image to validate
|
113
|
+
# @option options [String] :image_bytes Image in +PNG+ format. Can be obtained as ChunkyPNG::Image.to_blob()
|
114
|
+
# @option options [String] :image_path Path to image file
|
115
|
+
# @option options [String] :tag An optional tag to be associated with the validation checkpoint.
|
116
|
+
# @option options [Boolean] :ignore_mismatch If set to +true+ the server would ignore a negative
|
117
|
+
# result for the visual validation
|
118
|
+
# @example Image is a file
|
119
|
+
# eyes.check_region(image_path: '~/test/some_screenshot.png', region: my_region, tag: 'My Test')
|
120
|
+
# @example Image is a Applitools::Screenshot instance
|
121
|
+
# eyes.check_region(image: my_image, tag: 'My Test', region: my_region)
|
122
|
+
# @example Image is a +String+
|
123
|
+
# eyes.check_region(image_bytes: string_represents_image, tag: 'My Test', region: my_region)
|
124
|
+
def check_region(options)
|
125
|
+
options = { tag: nil, ignore_mismatch: false }.merge options
|
126
|
+
|
127
|
+
if disabled?
|
128
|
+
logger.info "check_region(image, #{options[:tag]}, #{options[:ignore_mismatch]}): Ignored"
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
|
132
|
+
Applitools::ArgumentGuard.not_nil options[:region], 'options[:region] can\'t be nil!'
|
133
|
+
image = get_image_from_options options
|
134
|
+
|
135
|
+
logger.info "check_region(image, #{options[:region]}, #{options[:tag]}, #{options[:ignore_mismatch]})"
|
136
|
+
|
137
|
+
if image.is_a? Applitools::Screenshot
|
138
|
+
self.viewport_size = Applitools::RectangleSize.new image.width, image.height if viewport_size.nil?
|
139
|
+
self.screenshot = EyesImagesScreenshot.new image
|
140
|
+
end
|
141
|
+
self.title = options[:tag] || ''
|
142
|
+
|
143
|
+
region_provider = Object.new
|
144
|
+
region_provider.instance_eval do
|
145
|
+
define_singleton_method :region do
|
146
|
+
options[:region]
|
147
|
+
end
|
148
|
+
define_singleton_method :coordinate_type do
|
149
|
+
Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
mr = check_window_base region_provider, options[:tag], options[:ignore_mismatch],
|
153
|
+
Applitools::EyesBase::USE_DEFAULT_TIMEOUT
|
154
|
+
mr.as_expected?
|
155
|
+
end
|
156
|
+
|
157
|
+
# Adds a mouse trigger
|
158
|
+
# @param [Symbol] action A mouse action. Can be one of +:click+, +:right_click+, +:double_click+, +:move+,
|
159
|
+
# +:down+, +:up+
|
160
|
+
# @param [Applitools::Region] control The control on which the trigger is activated
|
161
|
+
# (context relative coordinates).
|
162
|
+
# @param [Applitools::Location] cursor The cursor's position relative to the control.
|
163
|
+
def add_mouse_trigger(action, control, cursor)
|
164
|
+
add_mouse_trigger_base action, control, cursor
|
165
|
+
end
|
166
|
+
|
167
|
+
# Adds a keyboard trigger
|
168
|
+
# @param [Applitools::Region] control the control's context-relative region.
|
169
|
+
# @param text The trigger's text.
|
170
|
+
def add_text_trigger(control, text)
|
171
|
+
add_text_trigger_base control, text
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
def vp_size
|
177
|
+
viewport_size
|
178
|
+
end
|
179
|
+
|
180
|
+
def vp_size=(value)
|
181
|
+
Applitools::ArgumentGuard.not_nil 'value', value
|
182
|
+
@viewport_size = Applitools::RectangleSize.for value
|
183
|
+
end
|
184
|
+
|
185
|
+
alias get_viewport_size vp_size
|
186
|
+
alias set_viewport_size vp_size=
|
187
|
+
|
188
|
+
def get_image_from_options(options)
|
189
|
+
if options[:image].nil? && !options[:image].is_a?(Applitools::Screenshot)
|
190
|
+
if !options[:image_path].nil? && !options[:image_path].empty?
|
191
|
+
image = Applitools::Screenshot.new ChunkyPNG::Datastream.from_file(options[:image_path]).to_s
|
192
|
+
elsif options[:image_bytes].nil? && !options[:image_bytes].empty?
|
193
|
+
image = Applitools::Screenshot.new options[:image_bytes]
|
194
|
+
end
|
195
|
+
else
|
196
|
+
image = options[:image]
|
197
|
+
end
|
198
|
+
|
199
|
+
Applitools::ArgumentGuard.not_nil image, 'options[:image] can\'t be nil!'
|
200
|
+
|
201
|
+
image
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Applitools::Images
|
2
|
+
# @!visibility private
|
3
|
+
class EyesImagesScreenshot < ::Applitools::EyesScreenshot
|
4
|
+
SCREENSHOT_AS_IS = Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is].freeze
|
5
|
+
CONTEXT_RELATIVE = Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative].freeze
|
6
|
+
|
7
|
+
def initialize(image, options = {})
|
8
|
+
super image
|
9
|
+
return if (location = options[:location]).nil?
|
10
|
+
Applitools::ArgumentGuard.is_a? location, 'options[:location]', Applitools::Location
|
11
|
+
@bounds = Applitools::Region.new location.x, location.y, image.width, image.height
|
12
|
+
end
|
13
|
+
|
14
|
+
def convert_location(location, from, to)
|
15
|
+
Applitools::ArgumentGuard.not_nil location, 'location'
|
16
|
+
Applitools::ArgumentGuard.not_nil from, 'from'
|
17
|
+
Applitools::ArgumentGuard.not_nil to, 'to'
|
18
|
+
|
19
|
+
Applitools::ArgumentGuard.is_a? location, 'location', Applitools::Location
|
20
|
+
|
21
|
+
result = Applitools::Location.new location.x, location.y
|
22
|
+
return result if from == to
|
23
|
+
|
24
|
+
case from
|
25
|
+
when SCREENSHOT_AS_IS
|
26
|
+
raise "Coordinate type conversation error: #{from} -> #{to}" unless to == CONTEXT_RELATIVE
|
27
|
+
result.offset bounds
|
28
|
+
return result
|
29
|
+
when CONTEXT_RELATIVE
|
30
|
+
raise "Coordinate type conversation error: #{from} -> #{to}" unless to == SCREENSHOT_AS_IS
|
31
|
+
result.offset(Applitools::Location.new(-bounds.x, -bounds.y))
|
32
|
+
return result
|
33
|
+
else
|
34
|
+
raise "Coordinate type conversation error: #{from} -> #{to}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def convert_region_location(region, from, to)
|
39
|
+
Applitools::ArgumentGuard.not_nil region, 'region'
|
40
|
+
return Core::Region.new(0, 0, 0, 0) if region.empty?
|
41
|
+
|
42
|
+
Applitools::ArgumentGuard.not_nil from, 'from'
|
43
|
+
Applitools::ArgumentGuard.not_nil to, 'to'
|
44
|
+
|
45
|
+
updated_location = convert_location region.location, from, to
|
46
|
+
|
47
|
+
Applitools::Region.new updated_location.x, updated_location.y, region.width, region.height
|
48
|
+
end
|
49
|
+
|
50
|
+
def intersected_region(region, from, to = CONTEXT_RELATIVE)
|
51
|
+
Applitools::ArgumentGuard.not_nil region, 'region'
|
52
|
+
Applitools::ArgumentGuard.not_nil from, 'coordinates Type (from)'
|
53
|
+
|
54
|
+
return Applitools::Region.new(0, 0, 0, 0) if region.empty?
|
55
|
+
|
56
|
+
intersected_region = convert_region_location region, from, to
|
57
|
+
intersected_region.intersect bounds
|
58
|
+
return intersected_region if intersected_region.empty?
|
59
|
+
|
60
|
+
intersected_region.location = convert_location intersected_region.location, to, from
|
61
|
+
intersected_region
|
62
|
+
end
|
63
|
+
|
64
|
+
def location_in_screenshot(location, coordinates_type)
|
65
|
+
Applitools::ArgumentGuard.not_nil location, 'location'
|
66
|
+
Applitools::ArgumentGuard.not_nil coordinates_type, 'coordinates_type'
|
67
|
+
location = convert_location(location, coordinates_type, CONTEXT_RELATIVE)
|
68
|
+
|
69
|
+
unless bounds.contains? location.left, location.top
|
70
|
+
raise Applitools::OutOfBoundsException.new "Location #{location} is not available in screenshot!"
|
71
|
+
end
|
72
|
+
|
73
|
+
convert_location location, CONTEXT_RELATIVE, SCREENSHOT_AS_IS
|
74
|
+
end
|
75
|
+
|
76
|
+
def sub_screenshot(region, coordinates_type, throw_if_clipped)
|
77
|
+
Applitools::ArgumentGuard.not_nil region, 'region'
|
78
|
+
Applitools::ArgumentGuard.not_nil coordinates_type, 'coordinates_type'
|
79
|
+
|
80
|
+
sub_screen_region = intersected_region region, coordinates_type, SCREENSHOT_AS_IS
|
81
|
+
|
82
|
+
if sub_screen_region.empty? || (throw_if_clipped && !region.size_equals?(sub_screen_region))
|
83
|
+
Applitools::OutOfBoundsException.new "Region #{sub_screen_region} (#{coordinates_type}) is out of " \
|
84
|
+
" screenshot bounds #{bounds}"
|
85
|
+
end
|
86
|
+
|
87
|
+
sub_screenshot_image = Applitools::Screenshot.new image.crop(sub_screen_region.left, sub_screen_region.top,
|
88
|
+
sub_screen_region.width, sub_screen_region.height).to_datastream.to_blob
|
89
|
+
|
90
|
+
relative_sub_screenshot_region = convert_region_location(sub_screen_region, SCREENSHOT_AS_IS, CONTEXT_RELATIVE)
|
91
|
+
|
92
|
+
Applitools::Images::EyesImagesScreenshot.new sub_screenshot_image,
|
93
|
+
location: relative_sub_screenshot_region.location
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def bounds
|
99
|
+
@bounds ||= Applitools::Region.new(0, 0, image.width, image.height)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/eyes_images.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'eyes_core'
|
2
|
+
|
3
|
+
module Applitools::Images
|
4
|
+
# @!visibility private
|
5
|
+
class << self
|
6
|
+
# @!visibility private
|
7
|
+
def require_dir(dir)
|
8
|
+
Dir[File.join(File.dirname(File.expand_path(__FILE__)), 'applitools', dir, '*.rb')].sort.each do |f|
|
9
|
+
require f
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Applitools::Images.require_dir 'images'
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eyes_images
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Applitools Team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: eyes_core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.0.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.0.4
|
27
|
+
description: Applitools Ruby Images SDK
|
28
|
+
email:
|
29
|
+
- team@applitools.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- lib/applitools/images/eyes.rb
|
35
|
+
- lib/applitools/images/eyes_images_screenshot.rb
|
36
|
+
- lib/applitools/version.rb
|
37
|
+
- lib/eyes_images.rb
|
38
|
+
homepage: https://www.applitools.com
|
39
|
+
licenses:
|
40
|
+
- Apache License, Version 2.0
|
41
|
+
metadata:
|
42
|
+
yard.run: yri
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 2.6.8
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Applitools Ruby Images SDK
|
63
|
+
test_files: []
|