eyes_core 3.14.10 → 3.15.0.beta

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4624958021d0ecf5c443a0a9df7edc84158b2bf26b1caf920ccda6e19776f85
4
- data.tar.gz: 3494e2526ef93192d57c1604074fc497c668a6e140c0727650d76ec4d0043de2
3
+ metadata.gz: 1f5d2900e70b58643ee591bbef57b92a65fc2baf0e6756a4389a3200692a9520
4
+ data.tar.gz: 5323d53289f538a047d270b03d5c197c1e6d4935ab4e16e2697750dc26096bee
5
5
  SHA512:
6
- metadata.gz: 215fc9a1362141e7241ef3460be3e376d75d21b2fa660d43a454fe42149f1389fd8a49499b9fa8e2ca5dbc66ff397859d23c6553680673733ade5868b8a3f99a
7
- data.tar.gz: abde370aea21b82fe2a5da16a2cb1e7478c6c6737b0e9ded6342052b9201fcff136a69aab73f517dbae55f00aaaf10e5ab28831b06dc692029a09e4d01ae02fb
6
+ metadata.gz: 93eefa109d311ce4330400a4f37d545621c27fbf4e169f9b26a60ef10d59031fa634a8a370192fafdada8e75ab4e5587c68bab86c2c4ccf7e452c01881644500
7
+ data.tar.gz: cc276d91d1944b62ca602ecd3d64a74b18826e3df1afc9a6d12fe35094ee382e72ab35081f9f8e3990f203336ce544e69fb7f7a62adee2a7485411a87d50d89b
@@ -13,9 +13,15 @@ module Applitools::Connectivity
13
13
 
14
14
  SSL_CERT = File.join(File.dirname(File.expand_path(__FILE__)), '../../../certs/cacert.pem').to_s.freeze
15
15
  DEFAULT_TIMEOUT = 300
16
+ API_SESSIONS = '/api/sessions'.freeze
17
+ API_SESSIONS_RUNNING = API_SESSIONS + '/running/'.freeze
18
+ API_SINGLE_TEST = API_SESSIONS + '/'.freeze
16
19
 
17
- API_SESSIONS_RUNNING = '/api/sessions/running/'.freeze
18
- API_SINGLE_TEST = '/api/sessions/'.freeze
20
+ RENDER_INFO_PATH = API_SESSIONS + "/renderinfo".freeze
21
+ RENDER = '/render'.freeze
22
+
23
+ RESOURCES_SHA_256 = '/resources/sha256/'.freeze
24
+ RENDER_STATUS = '/render-status'.freeze
19
25
 
20
26
  HTTP_STATUS_CODES = {
21
27
  created: 201,
@@ -33,6 +39,83 @@ module Applitools::Connectivity
33
39
  self.server_url = url
34
40
  end
35
41
 
42
+ def rendering_info
43
+ response = get(server_url + RENDER_INFO_PATH, content_type: 'application/json')
44
+ raise Applitools::EyesError, 'Error getting render info' unless response.status == HTTP_STATUS_CODES[:ok]
45
+ Oj.load response.body
46
+ end
47
+
48
+ def render(service_url, access_key, requests)
49
+ uri = URI(service_url)
50
+ uri.path = RENDER
51
+ response = dummy_post(
52
+ uri,
53
+ body: requests.json,
54
+ headers: {
55
+ 'X-Auth-Token' => access_key
56
+ },
57
+ timeout: 10
58
+ )
59
+ raise Applitools::EyesError, "Error render processing (#{response.status}, #{response.body})" unless response.status == HTTP_STATUS_CODES[:ok]
60
+ Oj.load response.body
61
+ end
62
+
63
+ def render_put_resource(service_url, access_key, resource, render)
64
+ uri = URI(service_url)
65
+ uri.path = RESOURCES_SHA_256 + resource.hash
66
+ Applitools::EyesLogger.debug("PUT resource: #{uri}")
67
+ # Applitools::EyesLogger.debug("Resource content: #{resource.content}")
68
+ response = dummy_put(
69
+ uri,
70
+ body: resource.content,
71
+ content_type: resource.content_type,
72
+ headers: {
73
+ 'X-Auth-Token' => access_key
74
+ },
75
+ query: {'render-id' => render['renderId']}
76
+ )
77
+ raise Applitools::EyesError, "Error putting resource: #{response.status}, #{response.body}" unless response.status == HTTP_STATUS_CODES[:ok]
78
+ resource.hash
79
+ end
80
+
81
+ def render_status_by_id(service_url, access_key, running_renders_json)
82
+ uri = URI(service_url)
83
+ uri.path = RENDER_STATUS
84
+ response = dummy_post(
85
+ uri,
86
+ body: running_renders_json,
87
+ content_type: 'application/json',
88
+ headers: {
89
+ 'X-Auth-Token' => access_key
90
+ },
91
+ timeout: 2
92
+ )
93
+ raise Applitools::EyesError, "Error getting server status, #{response.status} #{response.body}" unless response.status == HTTP_STATUS_CODES[:ok]
94
+ Oj.load(response.body)
95
+ end
96
+
97
+ def download_resource(url)
98
+ Applitools::EyesLogger.debug "Fetching #{url}..."
99
+ resp_proc = proc do |u|
100
+ Faraday::Connection.new(
101
+ u,
102
+ ssl: { ca_file: SSL_CERT },
103
+ proxy: @proxy.nil? ? nil : @proxy.to_hash
104
+ ).send(:get) do |req|
105
+ req.options.timeout = DEFAULT_TIMEOUT
106
+ req.headers['Accept-Encoding'] = 'identity'
107
+ end
108
+ end
109
+ response = resp_proc.call(url)
110
+ redirect_count = 10
111
+ while response.status == 301 && redirect_count > 0 do
112
+ redirect_count -= 1
113
+ response = resp_proc.call(response.headers['location'])
114
+ end
115
+ Applitools::EyesLogger.debug 'Done!'
116
+ response
117
+ end
118
+
36
119
  def server_url=(url)
37
120
  @server_url = url.nil? ? DEFAULT_SERVER_URL : url
38
121
  unless @server_url.is_a? String
@@ -63,6 +146,7 @@ module Applitools::Connectivity
63
146
  # Applitools::EyesLogger.debug json_data
64
147
  res = long_post(URI.join(endpoint_url, session.id.to_s), content_type: 'application/octet-stream', body: body)
65
148
  raise Applitools::EyesError.new("Request failed: #{res.status} #{res.headers}") unless res.success?
149
+ # puts Oj.load(res.body)
66
150
  Applitools::MatchResult.new Oj.load(res.body)
67
151
  end
68
152
 
@@ -125,7 +209,7 @@ module Applitools::Connectivity
125
209
  end
126
210
 
127
211
  def post_dom_json(dom_data)
128
- Applitools::EyesLogger.debug 'About to send captured DOM...'
212
+ # Applitools::EyesLogger.debug 'About to send captured DOM...'
129
213
  request_body = Oj.dump(dom_data)
130
214
  # Applitools::EyesLogger.debug request_body
131
215
  processed_request_body = yield(request_body) if block_given?
@@ -153,11 +237,15 @@ module Applitools::Connectivity
153
237
  MAX_LONG_REQUEST_DELAY = 10 # seconds
154
238
  LONG_REQUEST_DELAY_MULTIPLICATIVE_INCREASE_FACTOR = 1.5
155
239
 
156
- [:get, :post, :delete].each do |method|
240
+ [:get, :post, :delete, :put].each do |method|
157
241
  define_method method do |url, options = {}|
158
242
  request(url, method, options)
159
243
  end
160
244
 
245
+ define_method "dummy_#{method}" do |url, options = {}|
246
+ dummy_request(url, method, options)
247
+ end
248
+
161
249
  define_method "long_#{method}" do |url, options = {}, request_delay = LONG_REQUEST_DELAY|
162
250
  long_request(url, method, request_delay, options)
163
251
  end
@@ -181,6 +269,7 @@ module Applitools::Connectivity
181
269
  url,
182
270
  ssl: { ca_file: SSL_CERT },
183
271
  proxy: @proxy.nil? ? nil : @proxy.to_hash
272
+ # proxy: Applitools::Connectivity::Proxy.new('http://localhost:8000').to_hash
184
273
  ).send(method) do |req|
185
274
  req.options.timeout = DEFAULT_TIMEOUT
186
275
  req.headers = DEFAULT_HEADERS.merge(options[:headers] || {})
@@ -190,6 +279,21 @@ module Applitools::Connectivity
190
279
  end
191
280
  end
192
281
 
282
+ def dummy_request(url, method, options = {})
283
+ Faraday::Connection.new(
284
+ url,
285
+ ssl: { ca_file: SSL_CERT },
286
+ proxy: @proxy.nil? ? nil : @proxy.to_hash
287
+ # proxy: Applitools::Connectivity::Proxy.new('http://localhost:8000').to_hash
288
+ ).send(method) do |req|
289
+ req.options.timeout = options[:timeout] || DEFAULT_TIMEOUT
290
+ req.headers = DEFAULT_HEADERS.merge(options[:headers] || {})
291
+ req.headers['Content-Type'] = options[:content_type] if options.key?(:content_type)
292
+ req.params = options[:query] || {}
293
+ req.body = options[:body]
294
+ end
295
+ end
296
+
193
297
  def long_request(url, method, request_delay, options = {})
194
298
  delay = request_delay
195
299
  options = { headers: {
@@ -231,3 +335,103 @@ module Applitools::Connectivity
231
335
  end
232
336
  end
233
337
  end
338
+
339
+ #
340
+ # /**
341
+ # *
342
+ # * @return The server timeout. (Seconds).
343
+ # */
344
+ # int getTimeout();
345
+ #
346
+ #
347
+ # /**
348
+ # * Deletes the given test result
349
+ # *
350
+ # * @param testResults The session to delete by test results.
351
+ # * @throws EyesException the exception is being thrown when deleteSession failed
352
+ # */
353
+ # void deleteSession(TestResults testResults);
354
+ #
355
+ #
356
+ # /**
357
+ # * Downloads string from a given Url
358
+ # *
359
+ # * @param uri The URI from which the IServerConnector will download the string
360
+ # * @param isSecondRetry Indicates if a retry is mandatory onFailed - 2 retries per request
361
+ # * @param listener the listener will be called when the request will be resolved.
362
+ # */
363
+ # void downloadString(URL uri, boolean isSecondRetry, IDownloadListener<String> listener);
364
+ #
365
+ # /**
366
+ # * Downloads string from a given Url.
367
+ # *
368
+ # * @param uri The URI from which the IServerConnector will download the string
369
+ # * @param isSecondRetry Indicates if a retry is mandatory onFailed - 2 retries per request
370
+ # * @param listener the listener will be called when the request will be resolved.
371
+ # * @return A future which will be resolved when the resources is downloaded.
372
+ # */
373
+ # IResourceFuture downloadResource(URL uri, boolean isSecondRetry, IDownloadListener<Byte[]> listener);
374
+ #
375
+ #
376
+ # /**
377
+ # * Posting the DOM snapshot to the server and returns
378
+ # * @param domJson JSON as String.
379
+ # * @return URL to the JSON that is stored by the server.
380
+ # */
381
+ # String postDomSnapshot(String domJson);
382
+ #
383
+ #
384
+ # /**
385
+ # * @return the render info from the server to be used later on.
386
+ # */
387
+ # RenderingInfo getRenderInfo();
388
+ #
389
+ # /**
390
+ # * Initiate a rendering using RenderingGrid API
391
+ # *
392
+ # * @param renderRequests renderRequest The current agent's running session.
393
+ # * @return {@code List<RunningRender>} The results of the render request
394
+ # */
395
+ # List<RunningRender> render(RenderRequest... renderRequests);
396
+ #
397
+ # /**
398
+ # * Check if resource exists on the server
399
+ # *
400
+ # * @param runningRender The running render (for second request only)
401
+ # * @param resource The resource to use
402
+ # * @return Whether resource exists on the server or not
403
+ # */
404
+ # boolean renderCheckResource(RunningRender runningRender, RGridResource resource);
405
+ #
406
+ # /**
407
+ # * Upload resource to the server
408
+ # *
409
+ # * @param runningRender The running render (for second request only)
410
+ # * @param resource The resource to upload
411
+ # * @param listener The callback wrapper for the upload result.
412
+ # * @return true if resource was uploaded
413
+ # */
414
+ # PutFuture renderPutResource(RunningRender runningRender, RGridResource resource, IResourceUploadListener listener);
415
+ #
416
+ # /**
417
+ # * Get the rendering status for current render
418
+ # *
419
+ # * @param runningRender The running render
420
+ # * @return RenderStatusResults The render's status
421
+ # */
422
+ # RenderStatusResults renderStatus(RunningRender runningRender);
423
+ #
424
+ # /**
425
+ # * Get the rendering status for current render
426
+ # *
427
+ # * @param renderIds The running renderId
428
+ # * @return The render's status
429
+ # */
430
+ # List<RenderStatusResults> renderStatusById(String... renderIds);
431
+ #
432
+ # IResourceFuture createResourceFuture(RGridResource gridResource);
433
+ #
434
+ # void setRenderingInfo(RenderingInfo renderInfo);
435
+
436
+
437
+
@@ -0,0 +1,16 @@
1
+ module Applitools
2
+ class AbstractConfiguration
3
+ attr_reader :config_hash
4
+ attr_accessor :validation_errors
5
+ extend Applitools::Concerns::EyesConfigurationDSL
6
+
7
+ def initialize
8
+ @config_hash = {}
9
+ self.validation_errors = {}
10
+ default_config = self.class.default_config
11
+ default_config.keys.each do |k|
12
+ send "#{k}=", default_config[k]
13
+ end
14
+ end
15
+ end
16
+ end
@@ -3,7 +3,8 @@
3
3
  module Applitools
4
4
  class AppOutput
5
5
  attr_reader :title, :screenshot64, :location
6
- attr_accessor :dom_url
6
+
7
+ attr_accessor :dom_url, :screenshot_url
7
8
 
8
9
  def initialize(title, screenshot64)
9
10
  @title = title
@@ -20,7 +21,8 @@ module Applitools
20
21
  result = {
21
22
  Title: title,
22
23
  Screenshot64: nil,
23
- Location: location.to_hash
24
+ Location: location.to_hash,
25
+ ScreenshotUrl: screenshot_url
24
26
  }
25
27
  result[:DomUrl] = dom_url if dom_url
26
28
  result
@@ -4,11 +4,11 @@ module Applitools
4
4
  class AppOutputWithScreenshot
5
5
  attr_reader :app_output, :screenshot
6
6
 
7
- def initialize(app_output, screenshot)
7
+ def initialize(app_output, screenshot, allow_empty_screenshot = false)
8
8
  raise Applitools::EyesIllegalArgument.new 'app_output is not kind of Applitools::AppOutput' unless
9
9
  app_output.is_a? Applitools::AppOutput
10
10
  raise Applitools::EyesIllegalArgument.new 'screenshot is not kind of Applitools::EyesScreenshot' unless
11
- screenshot.is_a? Applitools::EyesScreenshot
11
+ allow_empty_screenshot || screenshot.is_a?(Applitools::EyesScreenshot)
12
12
  @app_output = app_output
13
13
  @screenshot = screenshot
14
14
  end
@@ -0,0 +1,189 @@
1
+ module Applitools
2
+ module Concerns
3
+ module EyesConfigurationDSL
4
+ def methods_to_delegate
5
+ @methods_to_delegate ||= []
6
+ end
7
+
8
+ def accessor_methods
9
+ @accessor_methods ||= []
10
+ end
11
+
12
+ def collect_method(field_name)
13
+ accessor_methods.push field_name.to_sym
14
+ methods_to_delegate.push field_name.to_sym
15
+ methods_to_delegate.push "#{field_name}=".to_sym
16
+ end
17
+
18
+ def boolean_field(field_name)
19
+ collect_method field_name
20
+ define_method(field_name) do
21
+ return true if config_hash[field_name]
22
+ false
23
+ end
24
+
25
+ define_method("#{field_name}=") do |*args|
26
+ value = args.shift
27
+ if value
28
+ config_hash[field_name] = true
29
+ else
30
+ config_hash[field_name] = false
31
+ end
32
+ end
33
+
34
+ define_method("defined_#{field_name}?") do
35
+ true
36
+ end
37
+ end
38
+
39
+ def string_field(field_name)
40
+ collect_method field_name
41
+ define_method(field_name) do
42
+ return '' unless config_hash[field_name.to_sym].is_a? String
43
+ config_hash[field_name.to_sym]
44
+ end
45
+
46
+ define_method("#{field_name}=") do |*args|
47
+ value = args.shift
48
+ raise Applitools::EyesIllegalArgument, "Expected #{field_name} to be a String but got #{value.class} instead" unless value.is_a? String
49
+ config_hash[field_name.to_sym] = value.freeze
50
+ end
51
+
52
+ define_method("defined_#{field_name}?") do
53
+ !send(field_name).empty?
54
+ end
55
+ end
56
+
57
+ # def rectangle_size_field(field_name)
58
+ # collect_method field_name
59
+ # define_method(field_name) do
60
+ # return Applitools::RectangleSize.from_hash(width: 0, height: 0) unless config_hash[field_name.to_sym].is_a? Applitools::RectangleSize
61
+ # config_hash[field_name.to_sym]
62
+ # end
63
+ #
64
+ # define_method("#{field_name}=") do |*args|
65
+ # value = args.shift
66
+ # raise Applitools::EyesIllegalArgument, "Expected #{field_name} to be an Applitools::RectangleClass but got #{value.class} instead" unless value.is_a? Applitools::RectangleSize
67
+ # config_hash[field_name.to_sym] = value
68
+ # end
69
+ #
70
+ # define_method("defined_#{field_name}?") do
71
+ # send(field_name).square > 0
72
+ # end
73
+ # end
74
+
75
+ # def batch_info_field(field_name)
76
+ # collect_method field_name
77
+ # define_method(field_name) do
78
+ # config_hash[field_name.to_sym]
79
+ # end
80
+ #
81
+ # define_method("#{field_name}=") do |*args|
82
+ # value = args.shift
83
+ # raise(
84
+ # Applitools::EyesIllegalArgument,
85
+ # "Expected Applitools::BatchInfo but got #{value.class}"
86
+ # ) unless value.is_a? Applitools::BatchInfo
87
+ # config_hash[field_name.to_sym] = value
88
+ # end
89
+ #
90
+ # define_method("defined_#{field_name}?") do
91
+ # value = send(field_name)
92
+ # value.is_a? Applitools::BatchInfo
93
+ # end
94
+ # end
95
+
96
+ def object_field(field_name, klass)
97
+ collect_method field_name
98
+ define_method(field_name) do
99
+ config_hash[field_name.to_sym]
100
+ end
101
+ define_method("#{field_name}=") do |*args|
102
+ value = args.shift
103
+ raise(
104
+ Applitools::EyesIllegalArgument,
105
+ "Expected #{klass} but got #{value.class}"
106
+ ) unless value.is_a? klass
107
+ config_hash[field_name.to_sym] = value
108
+ end
109
+ define_method("defined_#{field_name}?") do
110
+ value = send(field_name)
111
+ value.is_a? klass
112
+ end
113
+ end
114
+
115
+ def int_field(field_name)
116
+ collect_method(field_name)
117
+ define_method(field_name) do
118
+ config_hash[field_name.to_sym]
119
+ # value =
120
+ # return value if value.is_a? Integer
121
+ # 0
122
+ end
123
+
124
+ define_method("#{field_name}=") do |*args|
125
+ value = args.shift
126
+ return config_hash[field_name.to_sym] = value if value.is_a? Integer
127
+ return config_hash[field_name.to_sym] = value.to_i if value.respond_to? :to_i
128
+ raise Applitools::EyesIllegalArgument, "Expected #{field_name} to be an Integer"
129
+ end
130
+
131
+ define_method("defined_#{field_name}?") do
132
+ value = send(field_name)
133
+ value.is_a? Integer
134
+ end
135
+ end
136
+
137
+ def enum_field(field_name, available_values_array)
138
+ collect_method(field_name)
139
+
140
+ define_method(field_name) do
141
+ config_hash[field_name.to_sym]
142
+ end
143
+
144
+ define_method("#{field_name}=") do |*args|
145
+ value = args.shift
146
+ raise(
147
+ Applitools::EyesIllegalArgument,
148
+ "Unknown #{field_name} #{value}. Allowed session types: " \
149
+ "#{available_values_array.join(', ')}"
150
+ ) unless available_values_array.include? value
151
+ config_hash[field_name.to_sym] = value
152
+ end
153
+
154
+ define_method("defined_#{field_name}?") do
155
+ available_values_array.include? send(field_name)
156
+ end
157
+ end
158
+
159
+ # def stitch_mode_field(field_name)
160
+ # collect_method field_name
161
+ # define_method(field_name) do
162
+ # config_hash[field_name.to_sym]
163
+ # end
164
+ #
165
+ # define_method("#{field_name}=") do |*args|
166
+ # value = args.shift
167
+ # raise(
168
+ # Applitools::EyesIllegalArgument,
169
+ # "Unknown stitch mode #{value}. Allowed session types: " \
170
+ # "#{Applitools::Selenium::Concerns::StitchModes::CSS}, " \
171
+ # "#{Applitools::Selenium::Concerns::StitchModes::SCROLL}"
172
+ # ) unless
173
+ # [
174
+ # Applitools::Selenium::Concerns::StitchModes::CSS,
175
+ # Applitools::Selenium::Concerns::StitchModes::SCROLL
176
+ # ].include? value
177
+ # config_hash[field_name.to_sym] = value
178
+ # end
179
+ #
180
+ # define_method("defined_#{field_name}?") do
181
+ # [
182
+ # Applitools::Concerns::SessionTypes::SEQUENTIAL,
183
+ # Applitools::Concerns::SessionTypes::PROGRESSION
184
+ # ].include? config_hash[field_name.to_sym]
185
+ # end
186
+ # end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,60 @@
1
+ require 'oj'
2
+ module Applitools
3
+ module Jsonable
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ base.class_eval do
7
+ class << self
8
+ attr_accessor :json_methods
9
+ end
10
+ @json_methods = {}
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ def json_field(*args)
16
+ options = Applitools::Utils.extract_options!(args)
17
+ field = args.first.to_sym
18
+ options = { method: field }.merge! options
19
+ json_methods[field] = options[:method]
20
+ if options[:method].to_sym == field
21
+ attr_accessor field
22
+ ruby_style_field = Applitools::Utils.underscore(field.to_s)
23
+ unless field.to_s == ruby_style_field
24
+ define_method(ruby_style_field) do
25
+ send(field)
26
+ end
27
+ define_method("#{ruby_style_field}=") do |v|
28
+ send("#{field}=", v)
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def json_fields(*args)
35
+ args.each { |m| json_field m }
36
+ end
37
+ end
38
+
39
+ def json_data
40
+ self.class.json_methods.sort.map {|k,v| [k, json_value(send(v))]}.to_h
41
+ end
42
+
43
+ def json
44
+ Oj.dump json_data
45
+ end
46
+
47
+ private
48
+
49
+ def json_value(value)
50
+ case value
51
+ when Hash
52
+ value.map { |k,v| [k, json_value(v)] }.sort {|a,b| a.first.to_s <=> b.first.to_s}.to_h
53
+ when Array
54
+ value.map { |el| json_value(el) }
55
+ else
56
+ value.respond_to?(:json_data) ? value.json_data : value
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,13 @@
1
+ module Applitools
2
+ module Concerns
3
+ module SessionTypes
4
+ extend self
5
+ SEQUENTIAL = 'SEQUENTIAL'
6
+ PROGRESSION = 'PROGRESSION'
7
+
8
+ def enum_values
9
+ [SEQUENTIAL, PROGRESSION]
10
+ end
11
+ end
12
+ end
13
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'applitools/core/helpers'
4
4
  require 'applitools/core/eyes_screenshot'
5
+ require 'applitools/core/eyes_base_configuration'
5
6
  require 'zlib'
6
7
 
7
8
  require_relative 'match_level_setter'
@@ -27,6 +28,8 @@ module Applitools
27
28
  SCREENSHOT_AS_IS = Applitools::EyesScreenshot::COORDINATE_TYPES[:screenshot_as_is].freeze
28
29
  CONTEXT_RELATIVE = Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative].freeze
29
30
 
31
+ attr_accessor :config
32
+
30
33
  def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
31
34
  def_delegators 'server_connector', :api_key, :api_key=, :server_url, :server_url=,
32
35
  :set_proxy, :proxy, :proxy=
@@ -36,11 +39,15 @@ module Applitools
36
39
  # Default value is false.
37
40
  # @return [boolean] verbose_results flag
38
41
 
39
- attr_accessor :app_name, :batch, :agent_id, :full_agent_id,
42
+
43
+ # attr_accessor :agent_id, :session_type, :app_name, :test_name,
44
+
45
+
46
+ attr_accessor :batch, :full_agent_id,
40
47
  :match_timeout, :save_new_tests, :save_failed_tests, :failure_reports, :default_match_settings, :cut_provider,
41
48
  :scale_ratio, :host_os, :host_app, :position_provider, :viewport_size, :verbose_results,
42
49
  :inferred_environment, :remove_session_if_matching, :server_scale, :server_remainder, :match_level, :exact,
43
- :compare_with_parent_branch
50
+ :compare_with_parent_branch, :results
44
51
 
45
52
  abstract_attr_accessor :base_agent_id
46
53
  abstract_method :capture_screenshot, true
@@ -48,12 +55,15 @@ module Applitools
48
55
  abstract_method :set_viewport_size, true
49
56
  abstract_method :get_viewport_size, true
50
57
 
51
- environment_attribute :branch_name, 'APPLITOOLS_BRANCH'
52
- environment_attribute :parent_branch_name, 'APPLITOOLS_PARENT_BRANCH'
53
- environment_attribute :baseline_env_name, 'APPLITOOLS_BASELINE_BRANCH'
58
+ # environment_attribute :branch_name, 'APPLITOOLS_BRANCH'
59
+ # environment_attribute :parent_branch_name, 'APPLITOOLS_PARENT_BRANCH'
60
+ # environment_attribute :baseline_env_name, 'APPLITOOLS_BASELINE_BRANCH'
61
+
62
+ def_delegators 'config', *Applitools::EyesBaseConfiguration.methods_to_delegate
54
63
 
55
64
  def initialize(server_url = nil)
56
65
  self.server_connector = Applitools::Connectivity::ServerConnector.new(server_url)
66
+ ensure_config
57
67
  self.disabled = false
58
68
  @viewport_size = nil
59
69
  self.match_timeout = DEFAULT_MATCH_TIMEOUT
@@ -61,12 +71,13 @@ module Applitools
61
71
  self.save_new_tests = true
62
72
  self.save_failed_tests = false
63
73
  self.remove_session_if_matching = false
64
- self.agent_id = nil
74
+ # self.agent_id = nil
65
75
  self.last_screenshot = nil
66
76
  @user_inputs = UserInputArray.new
67
77
  self.app_output_provider = Object.new
68
78
  self.verbose_results = false
69
79
  self.failed = false
80
+ self.results = []
70
81
  @inferred_environment = nil
71
82
  @properties = []
72
83
  @server_scale = 0
@@ -86,6 +97,10 @@ module Applitools
86
97
  self.compare_with_parent_branch = false
87
98
  end
88
99
 
100
+ def ensure_config
101
+ self.config = Applitools::EyesBaseConfiguration.new
102
+ end
103
+
89
104
  def match_level=(value)
90
105
  return @match_level = value if Applitools::MATCH_LEVEL.values.include?(value)
91
106
  return @match_level = Applitools::MATCH_LEVEL[value.to_sym] if Applitools::MATCH_LEVEL.keys.include?(value.to_sym)
@@ -173,10 +188,6 @@ module Applitools
173
188
  running_session && running_session.new_session?
174
189
  end
175
190
 
176
- def app_name
177
- !current_app_name.nil? && !current_app_name.empty? ? current_app_name : @app_name
178
- end
179
-
180
191
  def add_property(name, value)
181
192
  @properties << { name: name, value: value }
182
193
  end
@@ -207,7 +218,8 @@ module Applitools
207
218
  self.running_session = nil
208
219
  end
209
220
 
210
- def open_base(options)
221
+ def open_base(options = {})
222
+ self.results = []
211
223
  if disabled?
212
224
  logger.info "#{__method__} Ignored"
213
225
  return false
@@ -218,29 +230,17 @@ module Applitools
218
230
  raise Applitools::EyesError.new 'A test is already running'
219
231
  end
220
232
 
221
- Applitools::ArgumentGuard.hash options, 'open_base parameter', [:test_name]
222
- default_options = { session_type: 'SEQUENTIAL' }
223
- options = default_options.merge options
233
+ update_config_from_options(options)
224
234
 
225
- if app_name.nil?
226
- Applitools::ArgumentGuard.not_nil options[:app_name], 'options[:app_name]'
227
- self.current_app_name = options[:app_name]
228
- else
229
- self.current_app_name = app_name
230
- end
235
+ raise Applitools::EyesIllegalArgument, config.validation_errors.values.join('/n') unless config.valid?
231
236
 
232
- Applitools::ArgumentGuard.not_nil options[:test_name], 'options[:test_name]'
233
- self.test_name = options[:test_name]
234
237
  logger.info "Agent = #{full_agent_id}"
235
- logger.info "openBase(app_name: #{options[:app_name]}, test_name: #{options[:test_name]}," \
236
- " viewport_size: #{options[:viewport_size]})"
238
+ logger.info "openBase(app_name: #{app_name}, test_name: #{test_name}," \
239
+ " viewport_size: #{viewport_size.to_s})"
237
240
 
238
241
  raise Applitools::EyesError.new 'API key is missing! Please set it using api_key=' if
239
242
  api_key.nil? || (api_key && api_key.empty?)
240
243
 
241
- self.viewport_size = options[:viewport_size]
242
- self.session_type = options[:session_type]
243
-
244
244
  yield if block_given?
245
245
 
246
246
  self.open = true
@@ -249,6 +249,26 @@ module Applitools
249
249
  raise e
250
250
  end
251
251
 
252
+ def update_config_from_options(options)
253
+ # Applitools::ArgumentGuard.hash options, 'open_base parameter', [:test_name]
254
+ default_options = { session_type: 'SEQUENTIAL' }
255
+ options = default_options.merge options
256
+
257
+ if app_name && app_name.empty?
258
+ # Applitools::ArgumentGuard.not_nil options[:app_name], 'options[:app_name]'
259
+ self.app_name = options[:app_name] if options[:app_name]
260
+ end
261
+
262
+ # Applitools::ArgumentGuard.not_nil options[:test_name], 'options[:test_name]'
263
+ self.test_name = options[:test_name] if options[:test_name]
264
+ self.viewport_size = options[:viewport_size] if options[:viewport_size]
265
+ self.session_type = options[:session_type] if options[:session_type]
266
+ end
267
+
268
+ def merge_config(other_config)
269
+ config.merge(other_config)
270
+ end
271
+
252
272
  def ensure_running_session
253
273
  return if running_session
254
274
 
@@ -464,20 +484,24 @@ module Applitools
464
484
  end
465
485
 
466
486
  logger.info '--- Test passed'
487
+ self.results.push results
467
488
  return results
468
489
  ensure
469
490
  self.running_session = nil
470
- self.current_app_name = nil
491
+ self.app_name = ''
471
492
  end
472
493
 
473
494
  def compare_with_parent_branch=(value)
474
495
  @compare_with_parent_branch = value ? true : false
475
496
  end
476
497
 
498
+ # def rendering_info
499
+ # server_connector.rendering_info
500
+ # end
501
+ #
477
502
  private
478
503
 
479
- attr_accessor :running_session, :last_screenshot, :current_app_name, :test_name, :session_type,
480
- :scale_provider, :session_start_info, :should_match_window_run_once_on_timeout, :app_output_provider,
504
+ attr_accessor :running_session, :last_screenshot, :scale_provider, :session_start_info, :should_match_window_run_once_on_timeout, :app_output_provider,
481
505
  :failed, :server_connector
482
506
 
483
507
  attr_reader :user_inputs, :properties
@@ -500,7 +524,7 @@ module Applitools
500
524
 
501
525
  def app_environment
502
526
  Applitools::AppEnvironment.new os: host_os, hosting_app: host_app,
503
- display_size: @viewport_size, inferred: inferred_environment
527
+ display_size: viewport_size, inferred: inferred_environment
504
528
  end
505
529
 
506
530
  def open=(value)
@@ -666,6 +690,7 @@ module Applitools
666
690
  Applitools::AppOutput.new(a_title, compress_result).tap do |o|
667
691
  o.location = region.location unless region.empty?
668
692
  o.dom_url = dom_url unless dom_url && dom_url.empty?
693
+ o.screenshot_url = screenshot_url if respond_to?(:screenshot_url) && !screenshot_url.nil?
669
694
  end,
670
695
  screenshot
671
696
  )
@@ -0,0 +1,75 @@
1
+ require 'applitools/core/rectangle_size'
2
+ require 'applitools/core/concerns/session_types'
3
+ require 'applitools/core/batch_info'
4
+
5
+ module Applitools
6
+ class EyesBaseConfiguration < AbstractConfiguration
7
+ DEFAULT_CONFIG = {
8
+ branch_name: ENV['APPLITOOLS_BRANCH'] || '',
9
+ parent_branch_name: ENV['APPLITOOLS_PARENT_BRANCH'] || '',
10
+ baseline_branch_name: ENV['APPLITOOLS_BASELINE_BRANCH'] || '',
11
+ save_diffs: false
12
+ }.freeze
13
+
14
+ class << self
15
+ def default_config
16
+ DEFAULT_CONFIG
17
+ end
18
+ end
19
+
20
+ def initialize
21
+ super
22
+ self.batch_info = Applitools::BatchInfo.new
23
+ end
24
+
25
+ def merge(other_config)
26
+ return if self.object_id == other_config.object_id
27
+ (config_keys + other_config. config_keys).uniq do |k|
28
+ merge_key(other_config, k)
29
+ end
30
+ end
31
+
32
+ def merge_key(other_config, key)
33
+ return unless other_config.send("defined_#{key}?")
34
+ return unless self.respond_to? "#{key}="
35
+ self.send("#{key}=", other_config.send(key))
36
+ end
37
+
38
+ def config_keys
39
+ config_hash.keys
40
+ end
41
+
42
+ def to_s
43
+ config_keys.map do |k|
44
+ "#{k} = #{send(k)}"
45
+ end.join("\n")
46
+ end
47
+
48
+ def valid?
49
+ validation_errors.clear
50
+ validation_errors[:app_name] = ':app_name is required' if app_name.empty?
51
+ validation_errors[:test_name] = ':test_name is required' if test_name.empty?
52
+ validation_errors[:viewport_size] = ':viewport_size is required' if viewport_size.square.zero?
53
+ return true if validation_errors.keys.size.zero?
54
+ false
55
+ end
56
+
57
+ string_field :branch_name
58
+ string_field :parent_branch_name
59
+ string_field :baseline_branch_name
60
+ string_field :agent_id
61
+ string_field :environment_name
62
+ boolean_field :save_diffs
63
+ enum_field :session_type, Applitools::Concerns::SessionTypes.enum_values
64
+ object_field :batch_info, Applitools::BatchInfo
65
+ string_field :baseline_env_name
66
+ string_field :app_name
67
+ string_field :test_name
68
+ object_field :viewport_size, Applitools::RectangleSize
69
+
70
+ def short_description
71
+ "#{test_name} of #{app_name}"
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,25 @@
1
+ module Applitools
2
+ class Future
3
+ attr_accessor :result, :semaphore, :block, :thread
4
+
5
+ def initialize(semaphore, &block)
6
+ raise Applitools::EyesIllegalArgument, 'Applitools::Future must be initialized with a block' unless block_given?
7
+ self.block = block
8
+ self.semaphore = semaphore
9
+ self.thread = Thread.new do
10
+ begin
11
+ self.result = block.call(semaphore)
12
+ rescue StandardError => e
13
+ Applitools::EyesLogger.logger.error "Failed to execute future"
14
+ Applitools::EyesLogger.logger.error e.message
15
+ Applitools::EyesLogger.logger.error e.backtrace.join( ' ')
16
+ end
17
+ end
18
+ end
19
+
20
+ def get
21
+ thread.join(15)
22
+ result
23
+ end
24
+ end
25
+ end
@@ -82,6 +82,7 @@ module Applitools
82
82
  end
83
83
 
84
84
  def screenshot
85
+ return '' unless app_output.screenshot.respond_to?(:image)
85
86
  app_output.screenshot.image.to_blob
86
87
  end
87
88
 
@@ -248,7 +249,7 @@ module Applitools
248
249
  return unless @need_convert_ignored_regions_coordinates
249
250
  self.ignored_regions = @ignored_regions.map do |r|
250
251
  self.class.convert_coordinates(r, app_output.screenshot)
251
- end
252
+ end unless app_output.screenshot.nil?
252
253
  @need_convert_ignored_regions_coordinates = false
253
254
  end
254
255
 
@@ -271,7 +272,7 @@ module Applitools
271
272
  r.max_right_offset,
272
273
  r.max_bottom_offset
273
274
  ).padding(r.current_padding)
274
- end
275
+ end unless app_output.screenshot.nil?
275
276
  @need_convert_floating_regions_coordinates = false
276
277
  end
277
278
 
@@ -72,6 +72,18 @@ module Applitools::Utils
72
72
  {}
73
73
  end
74
74
 
75
+ def stringify_for_hash(value)
76
+ return value.stringify if value.respond_to? :stringify
77
+ case value
78
+ when Array
79
+ value.map { |el| stringify_for_hash(el) }.join('')
80
+ when Hash
81
+ value.keys.sort { |a, b| b.to_s <=> a.to_s }.map { |k| "#{k}#{stringify_for_hash(value[k])}"}.join('')
82
+ else
83
+ value.to_s
84
+ end
85
+ end
86
+
75
87
  private
76
88
 
77
89
  def convert_hash_keys(value, method)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Applitools
4
- VERSION = '3.14.10'.freeze
4
+ VERSION = '3.15.0.beta'.freeze
5
5
  end
data/lib/eyes_core.rb CHANGED
@@ -64,6 +64,7 @@ require_relative 'applitools/extensions'
64
64
  require_relative 'applitools/version'
65
65
  require_relative 'applitools/chunky_png_patch'
66
66
 
67
+ Applitools.require_dir 'core/concerns'
67
68
  Applitools.require_dir 'core'
68
69
  Applitools.require_dir 'connectivity'
69
70
  Applitools.require_dir 'utils'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eyes_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.14.10
4
+ version: 3.15.0.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Applitools Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-13 00:00:00.000000000 Z
11
+ date: 2019-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oily_png
@@ -122,6 +122,90 @@ dependencies:
122
122
  - - "<="
123
123
  - !ruby/object:Gem::Version
124
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
+ - !ruby/object:Gem::Dependency
196
+ name: rb-readline
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
125
209
  description: Don't use it directly, take a look at eyes_selenium, eyes_images or eyes_calabash
126
210
  gems instead.
127
211
  email:
@@ -173,6 +257,7 @@ files:
173
257
  - lib/applitools/chunky_png_patch.rb
174
258
  - lib/applitools/connectivity/proxy.rb
175
259
  - lib/applitools/connectivity/server_connector.rb
260
+ - lib/applitools/core/abstract_configuration.rb
176
261
  - lib/applitools/core/abstract_region.rb
177
262
  - lib/applitools/core/app_environment.rb
178
263
  - lib/applitools/core/app_output.rb
@@ -180,13 +265,18 @@ files:
180
265
  - lib/applitools/core/argument_guard.rb
181
266
  - lib/applitools/core/batch_info.rb
182
267
  - lib/applitools/core/class_name.rb
268
+ - lib/applitools/core/concerns/eyes_configuration_dsl.rb
269
+ - lib/applitools/core/concerns/jsonable.rb
270
+ - lib/applitools/core/concerns/session_types.rb
183
271
  - lib/applitools/core/debug_screenshot_provider.rb
184
272
  - lib/applitools/core/eyes_base.rb
273
+ - lib/applitools/core/eyes_base_configuration.rb
185
274
  - lib/applitools/core/eyes_screenshot.rb
186
275
  - lib/applitools/core/fixed_cut_provider.rb
187
276
  - lib/applitools/core/fixed_scale_provider.rb
188
277
  - lib/applitools/core/floating_region.rb
189
278
  - lib/applitools/core/fluent_interface.rb
279
+ - lib/applitools/core/future.rb
190
280
  - lib/applitools/core/hash_extension.rb
191
281
  - lib/applitools/core/helpers.rb
192
282
  - lib/applitools/core/location.rb
@@ -238,11 +328,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
328
  version: '0'
239
329
  required_rubygems_version: !ruby/object:Gem::Requirement
240
330
  requirements:
241
- - - ">="
331
+ - - ">"
242
332
  - !ruby/object:Gem::Version
243
- version: '0'
333
+ version: 1.3.1
244
334
  requirements: []
245
- rubygems_version: 3.0.3
335
+ rubyforge_project:
336
+ rubygems_version: 2.7.7
246
337
  signing_key:
247
338
  specification_version: 4
248
339
  summary: Core of the Applitools Ruby SDK