eyes_core 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.
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: []