eyes_core 3.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/ext/eyes_core/extconf.rb +3 -0
  3. data/ext/eyes_core/eyes_core.c +80 -0
  4. data/ext/eyes_core/eyes_core.h +24 -0
  5. data/lib/applitools/capybara.rb +8 -0
  6. data/lib/applitools/chunky_png/resampling.rb +148 -0
  7. data/lib/applitools/chunky_png_patch.rb +8 -0
  8. data/lib/applitools/connectivity/proxy.rb +3 -0
  9. data/lib/applitools/connectivity/server_connector.rb +118 -0
  10. data/lib/applitools/core/app_environment.rb +29 -0
  11. data/lib/applitools/core/app_output.rb +17 -0
  12. data/lib/applitools/core/app_output_with_screenshot.rb +22 -0
  13. data/lib/applitools/core/argument_guard.rb +35 -0
  14. data/lib/applitools/core/batch_info.rb +18 -0
  15. data/lib/applitools/core/eyes_base.rb +463 -0
  16. data/lib/applitools/core/eyes_screenshot.rb +35 -0
  17. data/lib/applitools/core/fixed_cut_provider.rb +61 -0
  18. data/lib/applitools/core/fixed_scale_provider.rb +14 -0
  19. data/lib/applitools/core/helpers.rb +18 -0
  20. data/lib/applitools/core/location.rb +84 -0
  21. data/lib/applitools/core/match_result.rb +16 -0
  22. data/lib/applitools/core/match_results.rb +9 -0
  23. data/lib/applitools/core/match_window_data.rb +34 -0
  24. data/lib/applitools/core/match_window_task.rb +86 -0
  25. data/lib/applitools/core/mouse_trigger.rb +39 -0
  26. data/lib/applitools/core/rectangle_size.rb +46 -0
  27. data/lib/applitools/core/region.rb +180 -0
  28. data/lib/applitools/core/screenshot.rb +49 -0
  29. data/lib/applitools/core/session.rb +15 -0
  30. data/lib/applitools/core/session_start_info.rb +33 -0
  31. data/lib/applitools/core/test_results.rb +55 -0
  32. data/lib/applitools/core/text_trigger.rb +24 -0
  33. data/lib/applitools/core/trigger.rb +8 -0
  34. data/lib/applitools/extensions.rb +18 -0
  35. data/lib/applitools/eyes_logger.rb +45 -0
  36. data/lib/applitools/images/eyes.rb +204 -0
  37. data/lib/applitools/images/eyes_images_screenshot.rb +102 -0
  38. data/lib/applitools/method_tracer.rb +23 -0
  39. data/lib/applitools/sauce.rb +2 -0
  40. data/lib/applitools/utils/eyes_selenium_utils.rb +348 -0
  41. data/lib/applitools/utils/image_delta_compressor.rb +146 -0
  42. data/lib/applitools/utils/image_utils.rb +146 -0
  43. data/lib/applitools/utils/utils.rb +68 -0
  44. data/lib/applitools/version.rb +3 -0
  45. data/lib/eyes_core.rb +70 -0
  46. metadata +273 -0
@@ -0,0 +1,146 @@
1
+ module Applitools::Utils
2
+ module ImageDeltaCompressor
3
+ extend self
4
+
5
+ BLOCK_SIZE = 10
6
+
7
+ # Compresses the target image based on the source image.
8
+ #
9
+ # +target+:: +ChunkyPNG::Canvas+ The image to compress based on the source image.
10
+ # +target_encoded+:: +Array+ The uncompressed image as binary string.
11
+ # +source+:: +ChunkyPNG::Canvas+ The source image used as a base for compressing the target image.
12
+ # +block_size+:: +Integer+ The width/height of each block.
13
+ #
14
+ # Returns +String+ The binary result (either the compressed image, or the uncompressed image if the compression
15
+ # is greater in length).
16
+ def compress_by_raw_blocks(target, target_encoded, source, block_size = BLOCK_SIZE)
17
+ # If we can't compress for any reason, return the target image as is.
18
+ if source.nil? || (source.height != target.height) || (source.width != target.width)
19
+ # Returning a COPY of the target binary string.
20
+ return String.new(target_encoded)
21
+ end
22
+
23
+ # Preparing the variables we need.
24
+ target_pixels = target.to_rgb_stream.unpack('C*')
25
+ source_pixels = source.to_rgb_stream.unpack('C*')
26
+ image_size = Dimension.new(target.width, target.height)
27
+ block_columns_count = (target.width / block_size) + ((target.width % block_size).zero? ? 0 : 1)
28
+ block_rows_count = (target.height / block_size) + ((target.height % block_size).zero? ? 0 : 1)
29
+
30
+ # IMPORTANT: The "-Zlib::MAX_WBITS" tells ZLib to create raw deflate compression, without the
31
+ # "Zlib headers" (this isn't documented in the Zlib page, I found this in some internet forum).
32
+ compressor = Zlib::Deflate.new(Zlib::BEST_COMPRESSION, -Zlib::MAX_WBITS)
33
+
34
+ compression_result = ''
35
+
36
+ # Writing the data header.
37
+ compression_result += PREAMBLE.encode('UTF-8')
38
+ compression_result += [FORMAT_RAW_BLOCKS].pack('C')
39
+ compression_result += [0].pack('S>') # Source id, Big Endian
40
+ compression_result += [block_size].pack('S>') # Big Endian
41
+
42
+ # We perform the compression for each channel.
43
+ 3.times do |channel|
44
+ block_number = 0
45
+ block_rows_count.times do |block_row|
46
+ block_columns_count.times do |block_column|
47
+ actual_channel_index = 2 - channel # Since the image bytes are BGR and the server expects RGB...
48
+ compare_result = compare_and_copy_block_channel_data(source_pixels, target_pixels, image_size, 3,
49
+ block_size, block_column, block_row, actual_channel_index)
50
+
51
+ unless compare_result.identical
52
+ channel_bytes = compare_result.channel_bytes
53
+ string_to_compress = [channel].pack('C')
54
+ string_to_compress += [block_number].pack('L>')
55
+ string_to_compress += channel_bytes.pack('C*')
56
+
57
+ compression_result += compressor.deflate(string_to_compress)
58
+
59
+ # If the compressed data so far is greater than the uncompressed representation of the target, just return
60
+ # the target.
61
+ if compression_result.length > target_encoded.length
62
+ compressor.finish
63
+ compressor.close
64
+ # Returning a copy of the target bytes.
65
+ return String.new(target_encoded)
66
+ end
67
+ end
68
+
69
+ block_number += 1
70
+ end
71
+ end
72
+ end
73
+
74
+ # Compress and flush any remaining uncompressed data in the input buffer.
75
+ compression_result += compressor.finish
76
+ compressor.close
77
+
78
+ # Returning the compressed result as a byte array.
79
+ compression_result
80
+ end
81
+
82
+ private
83
+
84
+ PREAMBLE = 'applitools'.freeze
85
+ FORMAT_RAW_BLOCKS = 3
86
+
87
+ Dimension = Struct.new(:width, :height)
88
+ CompareAndCopyBlockChannelDataResult = Struct.new(:identical, :channel_bytes)
89
+
90
+ # Computes the width and height of the image data contained in the block at the input column and row.
91
+ # +image_size+:: +Dimension+ The image size in pixels.
92
+ # +block_size+:: The block size for which we would like to compute the image data width and height.
93
+ # +block_column+:: The block column index.
94
+ # +block_row+:: The block row index.
95
+ # ++
96
+ # Returns the width and height of the image data contained in the block are returned as a +Dimension+.
97
+ def get_actual_block_size(image_size, block_size, block_column, block_row)
98
+ actual_width = [image_size.width - (block_column * block_size), block_size].min
99
+ actual_height = [image_size.height - (block_row * block_size), block_size].min
100
+ Dimension.new(actual_width, actual_height)
101
+ end
102
+
103
+ # Compares a block of pixels between the source and target and copies the target's block bytes to the result.
104
+ # +source_pixels+:: +Array+ of bytes, representing the pixels of the source image.
105
+ # +target_pixels+:: +Array+ of bytes, representing the pixels of the target image.
106
+ # +image_size+:: +Dimension+ The size of the source/target image (remember they must be the same size).
107
+ # +pixel_length+:: +Integer+ The number of bytes composing a pixel
108
+ # +block_size+:: +Integer+ The width/height of the block (block is a square, theoretically).
109
+ # +block_column+:: +Integer+ The block column index (when looking at the images as a grid of blocks).
110
+ # +block_row+:: +Integer+ The block row index (when looking at the images as a grid of blocks).
111
+ # +channel+:: +Integer+ The index of the channel we're comparing.
112
+ # ++
113
+ # Returns +CompareAndCopyBlockChannelDataResult+ object containing a flag saying whether the blocks are identical
114
+ # and a copy of the target block's bytes.
115
+ def compare_and_copy_block_channel_data(source_pixels, target_pixels, image_size, pixel_length, block_size,
116
+ block_column, block_row, channel)
117
+ identical = true
118
+
119
+ actual_block_size = get_actual_block_size(image_size, block_size, block_column, block_row)
120
+
121
+ # Getting the actual amount of data in the block we wish to copy.
122
+ actual_block_height = actual_block_size.height
123
+ actual_block_width = actual_block_size.width
124
+
125
+ stride = image_size.width * pixel_length
126
+
127
+ # Iterating the block's pixels and comparing the source and target.
128
+ channel_bytes = []
129
+ actual_block_height.times do |h|
130
+ offset = (((block_size * block_row) + h) * stride) + (block_size * block_column * pixel_length) + channel
131
+ actual_block_width.times do |_w|
132
+ source_byte = source_pixels[offset]
133
+ target_byte = target_pixels[offset]
134
+ identical = false if source_byte != target_byte
135
+ channel_bytes << target_byte
136
+ offset += pixel_length
137
+ end
138
+ end
139
+
140
+ # Returning the compare-and-copy result.
141
+ CompareAndCopyBlockChannelDataResult.new(identical, channel_bytes)
142
+ end
143
+
144
+ include Applitools::MethodTracer
145
+ end
146
+ end
@@ -0,0 +1,146 @@
1
+ require 'base64'
2
+ require 'tempfile'
3
+
4
+ module Applitools::Utils
5
+ # @!visibility private
6
+ QUADRANTS_COUNT = 4
7
+
8
+ RESAMPLE_INCREMENTALLY_FRACTION = 2
9
+
10
+ module ImageUtils
11
+ extend self
12
+
13
+ # Creates an image object from the PNG bytes.
14
+ # @param [String] png_bytes A binary string of the PNG bytes of the image.
15
+ # @return [ChunkyPNG::Canvas] An image object.
16
+ def png_image_from_bytes(png_bytes)
17
+ ChunkyPNG::Image.from_blob(png_bytes)
18
+ end
19
+
20
+ # Creates an image instance from a base64 representation of its PNG encoding.
21
+ # @param [String] png_bytes The Base64 representation of a PNG image.
22
+ # @return [ChunkyPNG::Canvas] An image object.
23
+ def png_image_from_base64(png_bytes)
24
+ png_image_from_bytes(Base64.decode64(png_bytes))
25
+ end
26
+
27
+ # Get the raw PNG bytes of an image.
28
+ # @param [ChunkyPNG::Canvas] image The image object for which to get the PNG bytes.
29
+ # @return [String] The PNG bytes of the image.
30
+ def bytes_from_png_image(image)
31
+ image.to_blob(:fast_rgb)
32
+ end
33
+
34
+ # Get the Base64 representation of the raw PNG bytes of an image.
35
+ # @param [ChunkyPNG::Canvas] image The image object for which to get the PNG bytes.
36
+ # @return [String] the Base64 representation of the raw PNG bytes of an image.
37
+ def base64_from_png_image(image)
38
+ Base64.encode64(bytes_from_png_image(image))
39
+ end
40
+
41
+ # Rotates a matrix 90 deg clockwise or counter clockwise (depending whether num_quadrants is positive or negative,
42
+ # respectively).
43
+ # @param [ChunkyPNG::Canvas] image The image to rotate.
44
+ # @param [Integer] num_quadrants The number of rotations to perform. Positive values are used for clockwise rotation
45
+ # and negative values are used for counter-clockwise rotation.
46
+ def quadrant_rotate!(image, num_quadrants)
47
+ num_quadrants %= QUADRANTS_COUNT
48
+ case num_quadrants
49
+ when 0
50
+ image
51
+ when 1
52
+ image.rotate_right!
53
+ when 2
54
+ image.rotate_180!
55
+ when 3
56
+ image.rotate_left!
57
+ end
58
+ end
59
+
60
+ # Cuts the image according to passed crop_region. The method mutates an image.
61
+ # @param [ChunkyPNG::Canvas] image The image to cut
62
+ # @param [Applitools::Region] crop_region The region which represents cut bounds.
63
+ # The area outside crop_region will be removed from the image.
64
+ def cut!(image, crop_region)
65
+ image.crop! crop_region.left, crop_region.top, crop_region.width, crop_region.height
66
+ end
67
+
68
+ # Cuts the image according to passed crop_region. The method returns new instance of the image
69
+ # without changing the source image.
70
+ # @param [ChunkyPNG::Canvas] image The image to cut
71
+ # @param [Applitools::Region] crop_region The region which represents cut bounds.
72
+ # The area outside crop_region will be removed from the image.
73
+ def cut(image, crop_region)
74
+ cut! image.dup, crop_region
75
+ end
76
+
77
+ # Scales image by given +scale factor+ by modifying given image
78
+ # @param [Applitools::Screenshot] image An image to scale. (The source image will be modified
79
+ # by invoking the method)
80
+ # @param [Float] scale_ratio Scale factor.
81
+ # @return [Applitools::Screenshot]
82
+ def scale!(image, scale_ratio)
83
+ return image if scale_ratio == 1
84
+ image_ratio = image.width.to_f / image.height.to_f
85
+ scale_width = (image.width * scale_ratio).ceil
86
+ scale_height = (scale_width / image_ratio).ceil
87
+ resize_image!(image, scale_width, scale_height)
88
+ end
89
+
90
+ def scale(image, scale_ratio)
91
+ scale!(image.dup, scale_ratio)
92
+ end
93
+
94
+ def resize_image!(image, new_width, new_height)
95
+ Applitools::ArgumentGuard.not_nil(new_width, 'new_width')
96
+ Applitools::ArgumentGuard.not_nil(new_height, 'new_height')
97
+ Applitools::ArgumentGuard.not_nil(image, 'image')
98
+ Applitools::ArgumentGuard.is_a?(image, 'image', Applitools::Screenshot)
99
+
100
+ raise Applitools::EyesIllegalArgument.new "Invalid width: #{new_width}" if new_width <= 0
101
+ raise Applitools::EyesIllegalArgument.new "Invalid height: #{new_height}" if new_height <= 0
102
+
103
+ return image if image.width == new_width && image.height == new_height
104
+
105
+ if new_width > image.width || new_height > image.height
106
+ image.resample_bicubic!(new_width, new_height)
107
+ else
108
+ scale_image_incrementally!(image, new_width, new_height)
109
+ end
110
+ end
111
+
112
+ def resize_image(image, new_width, new_height)
113
+ resize_image!(image.dup, new_width, new_height)
114
+ end
115
+
116
+ def scale_image_incrementally!(image, new_width, new_height)
117
+ current_width = image.width
118
+ current_height = image.height
119
+
120
+ while current_width != new_width || current_height != new_height
121
+ prev_current_width = current_width
122
+ prev_current_height = current_height
123
+ if current_width > new_width
124
+ current_width -= (current_width / RESAMPLE_INCREMENTALLY_FRACTION)
125
+ current_width = new_width if current_width < new_width
126
+ end
127
+
128
+ if current_height > new_height
129
+ current_height -= (current_height / RESAMPLE_INCREMENTALLY_FRACTION)
130
+ current_height = new_height if current_height < new_height
131
+ end
132
+
133
+ return image if prev_current_width == current_width && prev_current_height == current_height
134
+ Applitools::EyesLogger.debug "Incremental dimensions: #{current_width} x #{current_height}"
135
+ image.resample_bicubic!(current_width, current_height)
136
+ end
137
+ image
138
+ end
139
+
140
+ def scale_image_incrementally(image, new_width, new_height)
141
+ scale_image_incrementally!(image.dup, new_width, new_height)
142
+ end
143
+
144
+ include Applitools::MethodTracer
145
+ end
146
+ end
@@ -0,0 +1,68 @@
1
+ require 'bigdecimal'
2
+
3
+ module Applitools::Utils
4
+ extend self
5
+
6
+ def underscore(str)
7
+ str.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
8
+ end
9
+
10
+ def uncapitalize(str)
11
+ str[0, 1].downcase + str[1..-1]
12
+ end
13
+
14
+ def camelcase(str)
15
+ tokens = str.split('_')
16
+ uncapitalize(tokens.shift) + tokens.map(&:capitalize).join
17
+ end
18
+
19
+ def wrap(object)
20
+ if object.nil?
21
+ []
22
+ elsif object.respond_to?(:to_ary)
23
+ object.to_ary || [object]
24
+ else
25
+ [object]
26
+ end
27
+ end
28
+
29
+ def underscore_hash_keys(hash)
30
+ convert_hash_keys(hash, :underscore)
31
+ end
32
+
33
+ def camelcase_hash_keys(hash)
34
+ convert_hash_keys(hash, :camelcase)
35
+ end
36
+
37
+ def boolean_value(value)
38
+ if value
39
+ true
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ def symbolize_keys(hash)
46
+ hash.each_with_object({}) do |(k, v), memo|
47
+ memo[k.to_sym] = v
48
+ end
49
+ end
50
+
51
+ def extract_options!(array)
52
+ return array.pop if array.last.instance_of? Hash
53
+ {}
54
+ end
55
+
56
+ private
57
+
58
+ def convert_hash_keys(value, method)
59
+ case value
60
+ when Array
61
+ value.map { |v| convert_hash_keys(v, method) }
62
+ when Hash
63
+ Hash[value.map { |k, v| [send(method, k.to_s).to_sym, convert_hash_keys(v, method)] }]
64
+ else
65
+ value
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ module Applitools
2
+ VERSION = '3.0.4'.freeze
3
+ end
data/lib/eyes_core.rb ADDED
@@ -0,0 +1,70 @@
1
+ require 'forwardable'
2
+ require 'delegate'
3
+ require 'time'
4
+
5
+ module Applitools
6
+ # @!visibility private
7
+ class << self
8
+ # @!visibility private
9
+ def require_dir(dir)
10
+ Dir[File.join(File.dirname(File.expand_path(__FILE__)), 'applitools', dir, '*.rb')].sort.each do |f|
11
+ require f
12
+ end
13
+ end
14
+ end
15
+
16
+ # @!visibility private
17
+ class EyesError < StandardError; end
18
+ # @!visibility private
19
+ class EyesAbort < EyesError; end
20
+ # @!visibility private
21
+ class EyesIllegalArgument < EyesError; end
22
+ # @!visibility private
23
+ class EyesNoSuchFrame < EyesError; end
24
+ # @!visibility private
25
+ class OutOfBoundsException < EyesError; end
26
+ # @!visibility private
27
+ class EyesDriverOperationException < EyesError; end
28
+ # @!visibility private
29
+ class EyesNotOpenException < EyesError; end
30
+ # @!visibility private
31
+ class EyesCoordinateTypeConversionException < EyesError; end
32
+
33
+ # @!visibility private
34
+ class AbstractMethodCalled < EyesError
35
+ attr_accessor :method_name, :object
36
+
37
+ def initialize(method_name, object)
38
+ @method = method_name
39
+ @object = object
40
+ message = "Abstract method #{method_name} is called for #{object}. "\
41
+ 'You should override it in a descendant class.'
42
+ super message
43
+ end
44
+ end
45
+
46
+ # @!visibility private
47
+ class TestFailedError < StandardError
48
+ attr_accessor :test_results
49
+
50
+ def initialize(message, test_results = nil)
51
+ super(message)
52
+
53
+ @test_results = test_results
54
+ end
55
+ end
56
+
57
+ # @!visibility private
58
+ class NewTestError < TestFailedError; end
59
+ end
60
+
61
+ require_relative 'applitools/method_tracer'
62
+ require_relative 'applitools/extensions'
63
+ require_relative 'applitools/version'
64
+ require_relative 'applitools/chunky_png_patch'
65
+
66
+ Applitools.require_dir 'core'
67
+ Applitools.require_dir 'connectivity'
68
+ Applitools.require_dir 'utils'
69
+
70
+ require_relative 'applitools/eyes_logger'
metadata ADDED
@@ -0,0 +1,273 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eyes_core
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: oily_png
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: chunky_png
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.3.6
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.3.6
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: oj
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '3'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "<="
116
+ - !ruby/object:Gem::Version
117
+ version: 0.46.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "<="
123
+ - !ruby/object:Gem::Version
124
+ version: 0.46.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: pry-byebug
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: byebug
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: pry-doc
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: pry-stack_explorer
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ description: Applitools Ruby SDK
196
+ email:
197
+ - team@applitools.com
198
+ executables: []
199
+ extensions:
200
+ - ext/eyes_core/extconf.rb
201
+ extra_rdoc_files: []
202
+ files:
203
+ - ext/eyes_core/extconf.rb
204
+ - ext/eyes_core/eyes_core.c
205
+ - ext/eyes_core/eyes_core.h
206
+ - lib/applitools/capybara.rb
207
+ - lib/applitools/chunky_png/resampling.rb
208
+ - lib/applitools/chunky_png_patch.rb
209
+ - lib/applitools/connectivity/proxy.rb
210
+ - lib/applitools/connectivity/server_connector.rb
211
+ - lib/applitools/core/app_environment.rb
212
+ - lib/applitools/core/app_output.rb
213
+ - lib/applitools/core/app_output_with_screenshot.rb
214
+ - lib/applitools/core/argument_guard.rb
215
+ - lib/applitools/core/batch_info.rb
216
+ - lib/applitools/core/eyes_base.rb
217
+ - lib/applitools/core/eyes_screenshot.rb
218
+ - lib/applitools/core/fixed_cut_provider.rb
219
+ - lib/applitools/core/fixed_scale_provider.rb
220
+ - lib/applitools/core/helpers.rb
221
+ - lib/applitools/core/location.rb
222
+ - lib/applitools/core/match_result.rb
223
+ - lib/applitools/core/match_results.rb
224
+ - lib/applitools/core/match_window_data.rb
225
+ - lib/applitools/core/match_window_task.rb
226
+ - lib/applitools/core/mouse_trigger.rb
227
+ - lib/applitools/core/rectangle_size.rb
228
+ - lib/applitools/core/region.rb
229
+ - lib/applitools/core/screenshot.rb
230
+ - lib/applitools/core/session.rb
231
+ - lib/applitools/core/session_start_info.rb
232
+ - lib/applitools/core/test_results.rb
233
+ - lib/applitools/core/text_trigger.rb
234
+ - lib/applitools/core/trigger.rb
235
+ - lib/applitools/extensions.rb
236
+ - lib/applitools/eyes_logger.rb
237
+ - lib/applitools/images/eyes.rb
238
+ - lib/applitools/images/eyes_images_screenshot.rb
239
+ - lib/applitools/method_tracer.rb
240
+ - lib/applitools/sauce.rb
241
+ - lib/applitools/utils/eyes_selenium_utils.rb
242
+ - lib/applitools/utils/image_delta_compressor.rb
243
+ - lib/applitools/utils/image_utils.rb
244
+ - lib/applitools/utils/utils.rb
245
+ - lib/applitools/version.rb
246
+ - lib/eyes_core.rb
247
+ homepage: https://www.applitools.com
248
+ licenses:
249
+ - Apache License, Version 2.0
250
+ metadata:
251
+ yard.run: yri
252
+ post_install_message:
253
+ rdoc_options: []
254
+ require_paths:
255
+ - lib
256
+ - ext
257
+ required_ruby_version: !ruby/object:Gem::Requirement
258
+ requirements:
259
+ - - ">="
260
+ - !ruby/object:Gem::Version
261
+ version: '0'
262
+ required_rubygems_version: !ruby/object:Gem::Requirement
263
+ requirements:
264
+ - - ">="
265
+ - !ruby/object:Gem::Version
266
+ version: '0'
267
+ requirements: []
268
+ rubyforge_project:
269
+ rubygems_version: 2.6.8
270
+ signing_key:
271
+ specification_version: 4
272
+ summary: Applitools Ruby SDK
273
+ test_files: []