eyes_core 6.9.10 → 6.9.11

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: 1e32d5af62f8fda28d3477903aaf434b37458ceae19494f44e7acb5eb9114e0b
4
- data.tar.gz: ceb619f24f9ea0bd0be620dc4b24394bdfcec16ad66535b14d99a4bbcb1deaf8
3
+ metadata.gz: 4ae006da25788db912b4d6712f34ff1b8b4893b98357123151b33273808fe4e3
4
+ data.tar.gz: eaa492221c1b63304f625ed339258c8cd8ad88f4b9d9686f70a0c3039a5d6ed4
5
5
  SHA512:
6
- metadata.gz: a3cd67247f5a27a9f6b797c224b50467e8e68fd612098dd8e8c0ac073e5b245bafa12556a89d77077146fb907e38f6c6a8cc433752bbde644efde2780ed7e0eb
7
- data.tar.gz: b201181e1a883df59553632fc5ac4d95891e01ebfea609b51ee1985ff8efcf6fb05460e072bfc53105f9575a10d537960d707c5aa340299f661d61b20d2be4da
6
+ metadata.gz: 497ed2fae5815696d7fe8ef1f0ffa584c79e278e1b76c8890bd9fa5fe4026cd520b24860b22bea1a99c670bb977bef97de795aa56561d0c1808d2ce1a39d88fd
7
+ data.tar.gz: '004888674d2c57d4c37a1f9b54221d68bf1e031312ad0ca47b95c78204b768030e5a95eb403558a379008723462b3ca12022f663746dd14552f10afab12d1297'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [6.9.11](https://github.com/Applitools-Dev/sdk/compare/ruby/eyes_core@6.9.10...ruby/eyes_core@6.9.11) (2025-12-14)
4
+
5
+
6
+ ### Dependencies
7
+
8
+ * @applitools/nml-client bumped to 1.11.13
9
+
10
+ * @applitools/core-base bumped to 1.31.0
11
+ #### Features
12
+
13
+ * Baseline branch fallback list | FLD-3837 ([#3373](https://github.com/Applitools-Dev/sdk/issues/3373)) ([e94bb10](https://github.com/Applitools-Dev/sdk/commit/e94bb10ad6b49322a56e4ce6dfde560b237e9ac0))
14
+ * @applitools/core bumped to 4.54.0
15
+ #### Features
16
+
17
+ * Baseline branch fallback list | FLD-3837 ([#3373](https://github.com/Applitools-Dev/sdk/issues/3373)) ([e94bb10](https://github.com/Applitools-Dev/sdk/commit/e94bb10ad6b49322a56e4ce6dfde560b237e9ac0))
18
+
19
+
20
+
21
+ * @applitools/ec-client bumped to 1.12.15
22
+
23
+ * eyes_universal bumped to 4.54.0
24
+
25
+
3
26
  ## [6.9.10](https://github.com/Applitools-Dev/sdk/compare/ruby/eyes_core@6.9.9...ruby/eyes_core@6.9.10) (2025-12-07)
4
27
 
5
28
 
data/eyes_core.gemspec CHANGED
@@ -32,28 +32,12 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.metadata['yard.run'] = 'yri' # use "yard" to build full HTML docs.
34
34
 
35
- spec.add_dependency 'faraday'
36
- spec.add_dependency 'faraday_middleware'
37
- spec.add_dependency 'faraday-cookie_jar'
38
-
39
35
  spec.add_dependency 'oj'
40
- spec.add_dependency 'colorize'
41
36
  spec.add_dependency 'websocket'
42
- spec.add_dependency 'sorted_set'
43
- spec.add_dependency 'eyes_universal', "= 4.53.2"
37
+ spec.add_dependency 'eyes_universal', "= 4.54.0"
44
38
 
45
39
  spec.add_development_dependency 'bundler'
46
40
  spec.add_development_dependency 'rake'
47
41
  spec.add_development_dependency 'rspec', '>= 3'
48
42
  spec.add_development_dependency 'rubocop', '<= 0.46.0'
49
-
50
- # Exclude debugging support on Travis CI, due to its incompatibility with jruby and older rubies.
51
- unless ENV['TRAVIS']
52
- spec.add_development_dependency 'pry'
53
- spec.add_development_dependency 'pry-byebug'
54
- spec.add_development_dependency 'byebug'
55
- spec.add_development_dependency 'pry-doc'
56
- spec.add_development_dependency 'pry-stack_explorer'
57
- spec.add_development_dependency 'rb-readline'
58
- end
59
43
  end
@@ -1,44 +1,20 @@
1
1
  # frozen_string_literal: false
2
2
 
3
- require 'faraday'
4
- require 'faraday_middleware'
5
- require 'faraday-cookie_jar'
6
3
  require 'oj'
7
- require 'securerandom'
4
+ require 'uri'
8
5
 
9
6
  Oj.default_options = { :mode => :compat }
10
7
 
11
- require 'uri'
12
-
13
8
  module Applitools::Connectivity
9
+ # ServerConnector provides configuration for connecting to Applitools servers.
10
+ # All actual HTTP communication is now handled by the Universal SDK.
14
11
  class ServerConnector
15
- class << self
16
- attr_accessor :faraday_adapter, :connection_timeout
17
- end
18
- self.faraday_adapter = :net_http
19
- class ScreenshotUploadError < Applitools::EyesError; end
20
12
  extend Applitools::Helpers
21
- DEFAULT_SERVER_URL = 'https://eyesapi.applitools.com'.freeze
22
13
 
23
- SSL_CERT = File.join(File.dirname(File.expand_path(__FILE__)), '../../../certs/cacert.pem').to_s.freeze
14
+ DEFAULT_SERVER_URL = 'https://eyesapi.applitools.com'.freeze
24
15
  DEFAULT_TIMEOUT = 300_000
25
16
  API_SESSIONS = '/api/sessions'.freeze
26
17
  API_SESSIONS_RUNNING = API_SESSIONS + '/running/'.freeze
27
- API_SINGLE_TEST = API_SESSIONS + '/'.freeze
28
-
29
- RENDER_INFO_PATH = API_SESSIONS + '/renderinfo'.freeze
30
- RENDER = '/render'.freeze
31
-
32
- RESOURCES_SHA_256 = '/resources/sha256/'.freeze
33
- RENDER_STATUS = '/render-status'.freeze
34
- CLOSE_BATCH = '/api/sessions/batches/%s/close/bypointerid'.freeze
35
-
36
- HTTP_STATUS_CODES = {
37
- created: 201,
38
- accepted: 202,
39
- ok: 200,
40
- gone: 410
41
- }.freeze
42
18
 
43
19
  attr_accessor :server_url
44
20
  attr_reader :endpoint_url
@@ -60,142 +36,6 @@ module Applitools::Connectivity
60
36
  "eyes.sdk.ruby/#{Applitools::VERSION}"
61
37
  end
62
38
 
63
- def rendering_info
64
- response = long_get(URI.join(server_url, RENDER_INFO_PATH), content_type: 'application/json')
65
- unless response.status == HTTP_STATUS_CODES[:ok]
66
- raise Applitools::EyesError, "Error getting render info (#{response.status}})"
67
- end
68
- Oj.load response.body
69
- end
70
-
71
- def render(service_url, access_key, requests)
72
- uri = URI.join(URI(service_url), RENDER)
73
- response = dummy_post(
74
- uri,
75
- body: requests.json,
76
- headers: {
77
- 'X-Auth-Token' => access_key
78
- },
79
- timeout: 10
80
- )
81
- unless response.status == HTTP_STATUS_CODES[:ok]
82
- raise Applitools::EyesError, "Error render processing (#{response.status}, #{response.body})"
83
- end
84
- Oj.load response.body
85
- end
86
-
87
- def put_screenshot(rendering_info, screenshot)
88
- put_data(rendering_info, screenshot.image.to_blob, 'image/png', 'screenshot')
89
- end
90
-
91
- def put_dom(rendering_info, dom_data)
92
- put_data(rendering_info, dom_data, 'application/octet-stream', 'dom data')
93
- end
94
-
95
- def put_data(rendering_info, data, content_type, log_message_entity)
96
- uuid = SecureRandom.uuid
97
- upload_path = URI.parse(rendering_info.results_url.gsub(/__random__/, uuid))
98
- retry_count = 3
99
- wait = 0.5
100
- loop do
101
- raise ScreenshotUploadError, "Error uploading #{log_message_entity} (#{upload_path})" if retry_count <= 0
102
- Applitools::EyesLogger.info("Trying to upload #{log_message_entity} (#{upload_path})...")
103
- begin
104
- response = dummy_put(
105
- upload_path,
106
- body: data,
107
- headers: {
108
- 'x-ms-blob-type': 'BlockBlob',
109
- 'X-Auth-Token': rendering_info.access_token
110
- },
111
- query: URI.decode_www_form(upload_path.query).to_h,
112
- content_type: content_type
113
- )
114
- break if response.status == HTTP_STATUS_CODES[:created]
115
- Applitools::EyesLogger.info("Failed. Retrying in #{wait} seconds")
116
- sleep(wait)
117
- rescue StandardError => e
118
- Applitools::EyesLogger.error(e.class.to_s)
119
- Applitools::EyesLogger.error(e.message)
120
- Applitools::EyesLogger.info("Failed. Retrying in #{wait} seconds")
121
- sleep(wait)
122
- ensure
123
- retry_count -= 1
124
- wait *= 2
125
- end
126
- end
127
- Applitools::EyesLogger.info('Done.')
128
- upload_path.to_s
129
- end
130
-
131
- def render_put_resource(service_url, access_key, resource, render)
132
- uri = URI(service_url)
133
- uri.path = RESOURCES_SHA_256 + resource.hash
134
- Applitools::EyesLogger.debug("PUT resource: (#{resource.url}) - #{uri}")
135
- # Applitools::EyesLogger.debug("Resource content: #{resource.content}")
136
- response = dummy_put(
137
- uri,
138
- body: resource.content,
139
- content_type: resource.content_type,
140
- headers: {
141
- 'X-Auth-Token' => access_key
142
- },
143
- query: { 'render-id' => render['renderId'] }
144
- )
145
- unless response.status == HTTP_STATUS_CODES[:ok]
146
- raise Applitools::EyesError, "Error putting resource: #{response.status}, #{response.body}"
147
- end
148
- resource.hash
149
- end
150
-
151
- def render_status_by_id(service_url, access_key, running_renders_json)
152
- uri = URI(service_url)
153
- uri.path = RENDER_STATUS
154
- response = dummy_post(
155
- uri,
156
- body: running_renders_json,
157
- content_type: 'application/json',
158
- headers: {
159
- 'X-Auth-Token' => access_key
160
- },
161
- timeout: 2
162
- )
163
- unless response.status == HTTP_STATUS_CODES[:ok]
164
- raise Applitools::EyesError, "Error getting server status, #{response.status} #{response.body}"
165
- end
166
-
167
- Oj.load(response.body)
168
- end
169
-
170
- def download_resource(url, ua_string = nil, cookies=nil)
171
- Applitools::EyesLogger.debug "Fetching #{url}..."
172
- resp_proc = proc do |u|
173
- faraday_connection(u, false).send(:get) do |req|
174
- req.options.timeout = self.class.connection_timeout || DEFAULT_TIMEOUT
175
- req.headers[:accept_encoding] = 'identity'
176
- req.headers[:accept_language] = '*'
177
- req.headers[:user_agent] = ua_string if ua_string
178
- req.headers[:Cookie] = cookies.map { |h| [h[:name], h[:value]].join('=') }.join('; ') unless cookies.to_a.empty?
179
- end
180
- end
181
- response = resp_proc.call(url)
182
- Applitools::EyesLogger.debug "Done. (#{url} #{response.status})"
183
- response
184
- end
185
-
186
- def close_batch(batch_id)
187
- if 'true'.casecmp(ENV['APPLITOOLS_DONT_CLOSE_BATCHES'] || '') == 0
188
- return Applitools::EyesLogger.info(
189
- 'APPLITOOLS_DONT_CLOSE_BATCHES environment variable set to true. Doing nothing.'
190
- ) && false
191
- end
192
- Applitools::ArgumentGuard.not_nil(batch_id, 'batch_id')
193
- Applitools::EyesLogger.info("Called with #{batch_id}")
194
- url = CLOSE_BATCH % batch_id
195
- response = delete(URI.join(endpoint_url, url))
196
- Applitools::EyesLogger.info "delete batch is done with #{response.status} status"
197
- end
198
-
199
39
  def server_url=(url)
200
40
  if url
201
41
  uri = URI.parse(url)
@@ -207,7 +47,6 @@ module Applitools::Connectivity
207
47
  " (#{@server_url.class} is passed)"
208
48
  end
209
49
  @endpoint_url = URI.join(@server_url, API_SESSIONS_RUNNING).to_s
210
- @single_check_endpoint_url = URI.join(@server_url, API_SINGLE_TEST).to_s
211
50
  end
212
51
 
213
52
  def set_proxy(uri, user = nil, password = nil)
@@ -221,211 +60,5 @@ module Applitools::Connectivity
221
60
  end
222
61
  @proxy = value
223
62
  end
224
-
225
- def match_window(session, data)
226
- # Notice that this does not include the screenshot.
227
- json_data = Oj.dump(Applitools::Utils.camelcase_hash_keys(data.to_hash)).force_encoding('BINARY')
228
-
229
- body = if data.screenshot && data.app_output.screenshot_url.nil?
230
- content_type = 'application/octet-stream'
231
- [json_data.length].pack('L>') + json_data + data.screenshot
232
- else
233
- content_type = 'application/json'
234
- json_data
235
- end
236
-
237
- Applitools::EyesLogger.debug 'Sending match data...'
238
- Applitools::EyesLogger.debug json_data
239
- res = long_post(URI.join(endpoint_url, session.id.to_s), content_type: content_type, body: body)
240
- raise Applitools::EyesError.new("Request failed: #{res.status} #{res.headers}") unless res.success?
241
- # puts Oj.load(res.body)
242
- Applitools::MatchResult.new Oj.load(res.body)
243
- end
244
-
245
- RETRY_DELAY = 0.5
246
- RETRY_STEP_FACTOR = 1.5
247
- RETRY_MAX_DELAY = 5
248
-
249
- def match_single_window_data(data)
250
- # Notice that this does not include the screenshot.
251
- json_data = Oj.dump(data.to_hash).force_encoding('BINARY')
252
- body = [json_data.length].pack('L>') + json_data + data.screenshot
253
- # Applitools::EyesLogger.debug json_data
254
- begin
255
- Applitools::EyesLogger.debug 'Sending match data...'
256
- res = long_post(
257
- @single_check_endpoint_url,
258
- content_type: 'application/octet-stream',
259
- body: body,
260
- query: { agent_id: data.agent_id }
261
- )
262
- rescue Errno::EWOULDBLOCK, Faraday::ConnectionFailed
263
- @delays ||= request_delay(RETRY_DELAY, RETRY_STEP_FACTOR, RETRY_MAX_DELAY)
264
- begin
265
- sleep @delays.next
266
- rescue StopIteration
267
- raise Applitools::UnknownNetworkStackError.new('Unknown network stack error')
268
- end
269
- res = match_single_window_data(data)
270
- ensure
271
- @delays = nil
272
- end
273
- raise Applitools::EyesError.new("Request failed: #{res.status} #{res.headers} #{res.body}") unless res.success?
274
- res
275
- end
276
-
277
- def match_single_window(data)
278
- res = match_single_window_data(data)
279
- Applitools::TestResults.new Oj.load(res.body)
280
- end
281
-
282
- def start_session(session_start_info)
283
- request_body = session_start_info.json
284
- res = long_post(
285
- endpoint_url, body: request_body
286
- )
287
- raise Applitools::EyesError.new("Request failed: #{res.status} #{res.body} #{request_body}") unless res.success?
288
- response = Oj.load(res.body)
289
- Applitools::Session.new(response, res.status == HTTP_STATUS_CODES[:created])
290
- end
291
-
292
- def stop_session(session, aborted = nil, save = false)
293
- res = long_delete(URI.join(endpoint_url, session.id.to_s), query: { aborted: aborted, updateBaseline: save })
294
- raise Applitools::EyesError.new("Request failed: #{res.status}") unless res.success?
295
-
296
- response = Oj.load(res.body)
297
- Applitools::TestResults.new(response)
298
- end
299
-
300
- def post_dom_json(dom_data, rendering_info)
301
- Applitools::EyesLogger.debug 'About to send captured DOM...'
302
- request_body = dom_data
303
- Applitools::EyesLogger.debug request_body
304
- processed_request_body = yield(request_body) if block_given?
305
- location = put_dom(rendering_info, processed_request_body)
306
- Applitools::EyesLogger.debug 'Done!'
307
- location
308
- end
309
-
310
- private
311
-
312
- def faraday_connection(url, pass_user_agent_header = true)
313
- raise Applitools::NotUniversalServerRequestError.new(url)
314
- Faraday.new(
315
- url: url,
316
- ssl: { ca_file: SSL_CERT },
317
- proxy: @proxy.nil? ? nil : {uri: @proxy.uri}
318
- ) do |faraday|
319
- if pass_user_agent_header
320
- faraday.use(
321
- Applitools::Connectivity::UserAgentMiddleware,
322
- get_user_agent: @agent_id_proc,
323
- get_server_url: proc { server_url }
324
- )
325
- end
326
- faraday.use FaradayMiddleware::FollowRedirects
327
- faraday.use :cookie_jar
328
- faraday.adapter self.class.faraday_adapter
329
- end
330
- end
331
-
332
- DEFAULT_HEADERS = {
333
- 'Accept' => 'application/json',
334
- 'Content-Type' => 'application/json'
335
- }.freeze
336
-
337
- LONG_REQUEST_DELAY = 2 # seconds
338
- MAX_LONG_REQUEST_DELAY = 10 # seconds
339
- LONG_REQUEST_DELAY_MULTIPLICATIVE_INCREASE_FACTOR = 1.5
340
-
341
- [:get, :post, :delete, :put].each do |method|
342
- define_method method do |url, options = {}|
343
- request(url, method, options)
344
- end
345
-
346
- define_method "dummy_#{method}" do |url, options = {}|
347
- dummy_request(url, method, options)
348
- end
349
-
350
- define_method "long_#{method}" do |url, options = {}, request_delay = LONG_REQUEST_DELAY|
351
- long_request(url, method, request_delay, options)
352
- end
353
-
354
- private method, "long_#{method}"
355
- end
356
-
357
- def request_delay(first_delay, step_factor, max_delay)
358
- Enumerator.new do |y|
359
- delay = first_delay
360
- loop do
361
- y << delay
362
- delay *= step_factor
363
- break if delay > max_delay
364
- end
365
- end
366
- end
367
-
368
- def request(url, method, options = {})
369
- Applitools::EyesLogger.debug("Requesting #{url} (method: #{method})")
370
- response = faraday_connection(url).send(method) do |req|
371
- req.options.timeout = DEFAULT_TIMEOUT
372
- req.headers = DEFAULT_HEADERS.merge(options[:headers] || {})
373
- req.headers['Content-Type'] = options[:content_type] if options.key?(:content_type)
374
- req.params = { apiKey: api_key }.merge(options[:query] || {})
375
- req.body = options[:body]
376
- end
377
- Applitools::EyesLogger.debug("Got a response: #{response.status} #{response.reason_phrase}")
378
- response
379
- end
380
-
381
- def dummy_request(url, method, options = {})
382
- faraday_connection(url).send(method) do |req|
383
- req.options.timeout = options[:timeout] || DEFAULT_TIMEOUT
384
- req.headers = DEFAULT_HEADERS.merge(options[:headers] || {})
385
- req.headers['Content-Type'] = options[:content_type] if options.key?(:content_type)
386
- req.params = options[:query] || {}
387
- req.body = options[:body]
388
- end
389
- end
390
-
391
- def long_request(url, method, request_delay, options = {})
392
- delay = request_delay
393
- options = { headers: {
394
- 'Eyes-Expect' => '202+location'
395
- }.merge(eyes_date_header) }.merge! options
396
- res = request(url, method, options)
397
- check_status(res, delay)
398
- end
399
-
400
- def eyes_date_header
401
- { 'Eyes-Date' => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT') }
402
- end
403
-
404
- def check_status(res, delay)
405
- case res.status
406
- when HTTP_STATUS_CODES[:ok]
407
- res
408
- when HTTP_STATUS_CODES[:accepted]
409
- second_step_url = res.headers[:location]
410
- loop do
411
- delay = [MAX_LONG_REQUEST_DELAY, (delay * LONG_REQUEST_DELAY_MULTIPLICATIVE_INCREASE_FACTOR).round].min
412
- Applitools::EyesLogger.debug "Still running... retrying in #{delay}s"
413
- sleep delay
414
- second_step_options = {
415
- headers: {}.merge(eyes_date_header)
416
- }
417
- res = request(second_step_url, :get, second_step_options)
418
- break unless res.status == HTTP_STATUS_CODES[:ok]
419
- end
420
- check_status(res, delay)
421
- when HTTP_STATUS_CODES[:created]
422
- last_step_url = res.headers[:location]
423
- last_step_url.nil? ? res : request(last_step_url, :delete, headers: eyes_date_header)
424
- when HTTP_STATUS_CODES[:gone]
425
- raise Applitools::EyesError.new('The server task has gone.')
426
- else
427
- raise Applitools::EyesError.new('Unknown error processing long request')
428
- end
429
- end
430
63
  end
431
64
  end
@@ -35,10 +35,6 @@ module Applitools
35
35
  Applitools::TestResultSummary.new(all_universal_results)
36
36
  end
37
37
 
38
- def rendering_info(connector)
39
- @rendering_info ||= RenderingInfo.new(connector.rendering_info)
40
- end
41
-
42
38
  def universal_eyes_manager_config
43
39
  Applitools::UniversalEyesManagerConfig.classic
44
40
  end
@@ -49,7 +49,7 @@ module Applitools
49
49
  Applitools::ArgumentGuard.is_a?(viewport_size, 'viewport_size', Applitools::RectangleSize)
50
50
  Applitools::EyesLogger.info "Set viewport size #{viewport_size}"
51
51
  begin
52
- driver_config_json = driver.universal_driver_config
52
+ driver_config_json = Applitools::Selenium.universal_driver_config(driver)
53
53
  required_size = Applitools::RectangleSize.from_any_argument viewport_size
54
54
  @universal_client = Applitools::Connectivity::UniversalClient.new(self)
55
55
  @universal_client.core_set_viewport_size(driver_config_json, required_size.to_hash)
@@ -93,7 +93,7 @@ module Applitools
93
93
  :compare_with_parent_branch, :results, :runner, :allow_empty_screenshot, :screenshot_url
94
94
 
95
95
  abstract_attr_accessor :base_agent_id
96
- abstract_method :capture_screenshot, true
96
+ # Note: capture_screenshot removed - handled by Universal SDK
97
97
  abstract_method :title, true
98
98
  abstract_method :set_viewport_size, true
99
99
  abstract_method :get_viewport_size, true
@@ -134,13 +134,8 @@ module Applitools
134
134
  @inferred_environment = nil
135
135
  @server_scale = 0
136
136
  @server_remainder = 0
137
- get_app_output_method = ->(r, s) { get_app_output_with_screenshot r, s }
138
-
139
- app_output_provider.instance_eval do
140
- define_singleton_method :app_output do |r, s|
141
- get_app_output_method.call(r, s)
142
- end
143
- end
137
+ # Note: app_output_provider.app_output is now handled by Universal SDK
138
+ # The old get_app_output_with_screenshot method has been removed
144
139
 
145
140
  # self.exact = nil
146
141
  self.match_level = Applitools::MatchLevel::STRICT
@@ -221,6 +216,11 @@ module Applitools
221
216
  return Applitools::TestResults.new
222
217
  end
223
218
 
219
+ # Check if the session is still open before logging abort
220
+ if universal_eyes && universal_eyes.closed_or_aborted
221
+ # Session already closed, no need to abort or log
222
+ return nil
223
+ end
224
224
 
225
225
  # if running_session.nil?
226
226
  # logger.info 'Closed'
@@ -447,7 +447,7 @@ module Applitools
447
447
  return false
448
448
  end
449
449
 
450
- logger.info "close(#{throw_exception})"
450
+ logger.debug "close(#{throw_exception})"
451
451
  raise Applitools::EyesError.new 'Eyes not open' unless open?
452
452
 
453
453
  if !running_session && !universal_eyes
@@ -459,7 +459,7 @@ module Applitools
459
459
  # is_new_session = running_session.new_session?
460
460
  # session_results_url = running_session.url
461
461
 
462
- logger.info 'Ending server session...'
462
+ logger.debug 'Ending server session...'
463
463
 
464
464
  # save = is_new_session && save_new_tests || !is_new_session && failed && save_failed_tests
465
465
 
@@ -542,7 +542,7 @@ module Applitools
542
542
  self.last_screenshot = nil
543
543
  clear_user_inputs
544
544
 
545
- logger.info 'Getting results...'
545
+ logger.debug 'Getting results...'
546
546
 
547
547
  universal_results = universal_eyes.eyes_get_results # Array even for one test
548
548
  # require 'pry'
@@ -552,13 +552,16 @@ module Applitools
552
552
  logger.error "--- Error (#{universal_results[:reason]}) : #{universal_results[:message]}"
553
553
  error_message = "Test '#{test_name}' of '#{app_name}' " \
554
554
  "is failed! Details : #{universal_results[:message]}"
555
- raise Applitools::TestFailedError.new error_message, results if throw_exception
556
- return universal_results
555
+ raise Applitools::TestFailedError.new error_message, nil if throw_exception
556
+ return nil
557
557
  end
558
558
  key_transformed_results = Applitools::Utils.deep_stringify_keys(universal_results)
559
559
  results = key_transformed_results.map {|result| Applitools::TestResults.new(result) }
560
560
  # results = results.first if results.size >= 1
561
561
 
562
+ # Handle case where there are no results (e.g., no checkpoints before close)
563
+ return results if results.empty?
564
+
562
565
  session_results_url = results.first.url
563
566
  # results = server_connector.stop_session running_session, false, save
564
567
 
@@ -768,59 +771,7 @@ module Applitools
768
771
  end
769
772
  end
770
773
 
771
- def get_app_output_with_screenshot(region_provider, _last_screenshot)
772
- captured_dom_data = dom_data
773
- logger.info 'Getting screenshot...'
774
- screenshot = capture_screenshot
775
- logger.info 'Done getting screenshot!'
776
- region = region_provider.region
777
-
778
- unless region.empty?
779
- screenshot = screenshot.sub_screenshot region, region_provider.coordinate_type, false
780
- end
781
-
782
- screenshot = yield(screenshot) if block_given?
783
-
784
- logger.info 'Getting title...'
785
- a_title = title
786
- logger.info 'Done!'
787
- Applitools::AppOutputWithScreenshot.new(
788
- Applitools::AppOutput.new(a_title, screenshot).tap do |o|
789
- o.location = region.location unless region.empty?
790
- o.on_need_screenshot_url do
791
- return unless screenshot
792
- server_connector.put_screenshot(
793
- runner.rendering_info(server_connector),
794
- screenshot
795
- )
796
- end
797
- o.on_need_dom_url do
798
- unless captured_dom_data.empty?
799
- begin
800
- logger.info 'Processing DOM..'
801
- dom_url = server_connector.post_dom_json(captured_dom_data, runner.rendering_info(server_connector)) do |json|
802
- io = StringIO.new
803
- gz = Zlib::GzipWriter.new(io)
804
- gz.write(json.encode('UTF-8'))
805
- gz.close
806
- result = io.string
807
- io.close
808
- result
809
- end
810
- logger.info 'Done'
811
- logger.info dom_url
812
- rescue Applitools::EyesError => e
813
- logger.warn e.message
814
- dom_url = nil
815
- end
816
- dom_url
817
- end
818
- end
819
- end,
820
- screenshot,
821
- allow_empty_screenshot
822
- )
823
- end
774
+ # Note: get_app_output_with_screenshot removed - screenshots now handled by Universal SDK
824
775
 
825
776
  class UserInputArray < Array
826
777
  def add(trigger)
@@ -35,7 +35,7 @@ module Applitools
35
35
  end
36
36
 
37
37
  update_config_from_options(options)
38
- universal_driver_config = driver.universal_driver_config if self.class.name != 'Applitools::Images::Eyes'
38
+ universal_driver_config = Applitools::Selenium.universal_driver_config(driver) if self.class.name != 'Applitools::Images::Eyes'
39
39
 
40
40
  # Ensure we have a runner (default to ClassicRunner if not provided)
41
41
  self.runner ||= Applitools::ClassicRunner.new
@@ -76,7 +76,8 @@ module Applitools
76
76
  result = result[0] if result.is_a?(Array)
77
77
 
78
78
  if result.is_a? Hash
79
- logger.info "---Test aborted" if !result[:message] && !result[:stack]
79
+ # Only log "Test aborted" if it wasn't already closed
80
+ logger.info "---Test aborted" if !closed_or_aborted && !result[:message] && !result[:stack]
80
81
  else
81
82
  # TestCheckFrameInFrame_Fully_Fluent_VG\
82
83
  # require('pry')
@@ -105,16 +106,16 @@ module Applitools
105
106
 
106
107
  raise Applitools::EyesIllegalArgument, config.validation_errors.values.join('/n') unless config.valid?
107
108
 
108
- logger.info "Agent = #{full_agent_id}"
109
- logger.info "open(app_name: #{app_name}, test_name: #{test_name}," \
109
+ logger.debug "Agent = #{full_agent_id}"
110
+ logger.debug "open(app_name: #{app_name}, test_name: #{test_name}," \
110
111
  " viewport_size: #{viewport_size})"
111
112
 
112
113
  raise Applitools::EyesError.new 'API key is missing! Please set it using api_key=' if
113
114
  api_key.nil? || (api_key && api_key.empty?)
114
115
 
115
- logger.info "Batch is #{@batch}" if @batch
116
+ logger.debug "Batch is #{@batch}" if @batch
116
117
  app_env = app_environment if respond_to? :app_environment
117
- logger.info "Application environment is #{app_env}"
118
+ logger.debug "Application environment is #{app_env}"
118
119
  test_info = "'#{test_name}' of '#{app_name}' #{app_env}"
119
120
  logger.info "--- New test started - #{test_info}"
120
121
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Applitools
4
4
  module EyesCore
5
- VERSION = '6.9.10'.freeze
5
+ VERSION = '6.9.11'.freeze
6
6
  end
7
7
 
8
8
  VERSION = Applitools::EyesCore::VERSION
@@ -5,7 +5,6 @@
5
5
 
6
6
  require 'json'
7
7
  require 'securerandom'
8
- require 'colorize'
9
8
  require 'websocket'
10
9
  require 'uri'
11
10
  require 'eyes_universal'
@@ -343,6 +342,16 @@ module Applitools::Connectivity
343
342
  Applitools::EyesUniversal::UniversalServerControl.configure(mask_log)
344
343
  @universal_server_control = Applitools::EyesUniversal::UniversalServerControl.instance
345
344
  @web_socket = @universal_server_control.new_server_socket_connection
345
+
346
+ # Check if socket connection was successfully established
347
+ if @web_socket.nil?
348
+ raise Applitools::EyesError.new(
349
+ "Failed to establish connection to Universal SDK server. " \
350
+ "The server may not be running or the connection was refused. " \
351
+ "Check server logs for more details."
352
+ )
353
+ end
354
+
346
355
  socket_handshake
347
356
  session_init(eyes)
348
357
  # connect_and_configure_socket(socket_uri)
@@ -439,7 +448,8 @@ module Applitools::Connectivity
439
448
  end
440
449
  raise Applitools::EyesError.new "Empty result on #{name}" if web_socket_result.empty?
441
450
 
442
- web_socket_result += receive_result(name) if @web_socket.ready?
451
+ # Check if more data is available without blocking (Ruby 3.0+ compatibility)
452
+ web_socket_result += receive_result(name) if IO.select([@web_socket], nil, nil, 0)
443
453
  web_socket_result
444
454
  end
445
455
 
metadata CHANGED
@@ -1,57 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eyes_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.9.10
4
+ version: 6.9.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Applitools Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-12-07 00:00:00.000000000 Z
11
+ date: 2025-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: faraday
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: faraday_middleware
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: faraday-cookie_jar
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
13
  - !ruby/object:Gem::Dependency
56
14
  name: oj
57
15
  requirement: !ruby/object:Gem::Requirement
@@ -66,20 +24,6 @@ dependencies:
66
24
  - - ">="
67
25
  - !ruby/object:Gem::Version
68
26
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: colorize
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
27
  - !ruby/object:Gem::Dependency
84
28
  name: websocket
85
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,34 +38,20 @@ dependencies:
94
38
  - - ">="
95
39
  - !ruby/object:Gem::Version
96
40
  version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: sorted_set
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
41
  - !ruby/object:Gem::Dependency
112
42
  name: eyes_universal
113
43
  requirement: !ruby/object:Gem::Requirement
114
44
  requirements:
115
45
  - - '='
116
46
  - !ruby/object:Gem::Version
117
- version: 4.53.2
47
+ version: 4.54.0
118
48
  type: :runtime
119
49
  prerelease: false
120
50
  version_requirements: !ruby/object:Gem::Requirement
121
51
  requirements:
122
52
  - - '='
123
53
  - !ruby/object:Gem::Version
124
- version: 4.53.2
54
+ version: 4.54.0
125
55
  - !ruby/object:Gem::Dependency
126
56
  name: bundler
127
57
  requirement: !ruby/object:Gem::Requirement
@@ -178,90 +108,6 @@ dependencies:
178
108
  - - "<="
179
109
  - !ruby/object:Gem::Version
180
110
  version: 0.46.0
181
- - !ruby/object:Gem::Dependency
182
- name: pry
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: pry-byebug
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'
209
- - !ruby/object:Gem::Dependency
210
- name: byebug
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- version: '0'
223
- - !ruby/object:Gem::Dependency
224
- name: pry-doc
225
- requirement: !ruby/object:Gem::Requirement
226
- requirements:
227
- - - ">="
228
- - !ruby/object:Gem::Version
229
- version: '0'
230
- type: :development
231
- prerelease: false
232
- version_requirements: !ruby/object:Gem::Requirement
233
- requirements:
234
- - - ">="
235
- - !ruby/object:Gem::Version
236
- version: '0'
237
- - !ruby/object:Gem::Dependency
238
- name: pry-stack_explorer
239
- requirement: !ruby/object:Gem::Requirement
240
- requirements:
241
- - - ">="
242
- - !ruby/object:Gem::Version
243
- version: '0'
244
- type: :development
245
- prerelease: false
246
- version_requirements: !ruby/object:Gem::Requirement
247
- requirements:
248
- - - ">="
249
- - !ruby/object:Gem::Version
250
- version: '0'
251
- - !ruby/object:Gem::Dependency
252
- name: rb-readline
253
- requirement: !ruby/object:Gem::Requirement
254
- requirements:
255
- - - ">="
256
- - !ruby/object:Gem::Version
257
- version: '0'
258
- type: :development
259
- prerelease: false
260
- version_requirements: !ruby/object:Gem::Requirement
261
- requirements:
262
- - - ">="
263
- - !ruby/object:Gem::Version
264
- version: '0'
265
111
  description: Don't use it directly, take a look at eyes_selenium or eyes_images gems
266
112
  instead.
267
113
  email: