eyes_core 3.14.10 → 3.15.0.beta

Sign up to get free protection for your applications and to get access to all the features.
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