eyes_selenium 3.15.29 → 3.15.30

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.
@@ -1,12 +1,13 @@
1
1
  module Applitools
2
2
  module Selenium
3
3
  class RenderResources < Hash
4
+ class ResourceMissingInCache < EyesError; end
4
5
  def []=(key, value)
5
- raise Applitools::EyesIllegalArgument, "Expected key to be an instance of URI (but got #{key.class})" unless
6
+ raise Applitools::EyesIllegalArgument, "Expected key to be an instance of URI (but got #{key.class}) - #{key}" unless
6
7
  key.is_a? URI
7
- raise Applitools::EyesIllegalArgument, "Expected key to be an instance of Applitools::Selenium::VGResource" \
8
- " (but got #{value.class})" unless value.is_a? Applitools::Selenium::VGResource
9
- return super
8
+ raise Applitools::EyesIllegalArgument, "Expected value to be an instance of Applitools::Selenium::VGResource" \
9
+ " (but got #{value.class}) - #{key}:#{value}" unless value.is_a? Applitools::Selenium::VGResource
10
+ super
10
11
  end
11
12
  end
12
13
  end
@@ -519,7 +519,7 @@ module Applitools::Selenium
519
519
  def dom_data
520
520
  return {} if prevent_dom_processing
521
521
  begin
522
- Applitools::Selenium::DomCapture.get_window_dom(driver, logger)
522
+ Applitools::Selenium::DomCapture.full_window_dom(driver, server_connector, logger, position_provider)
523
523
  rescue Applitools::EyesError => e
524
524
  logger.error "DOM capture failed! #{e.message}"
525
525
  return {}
@@ -10,7 +10,7 @@ module Applitools
10
10
 
11
11
  attr_accessor :script, :running_tests, :all_blobs, :resource_urls, :resource_cache, :put_cache, :server_connector,
12
12
  :rendering_info, :request_resources, :dom_url_mod, :result, :region_selectors, :size_mode,
13
- :region_to_check, :script_hooks, :visual_grid_manager
13
+ :region_to_check, :script_hooks, :visual_grid_manager, :discovered_resources
14
14
 
15
15
  def initialize(name, script_result, visual_grid_manager, server_connector, region_selectors, size_mode,
16
16
  region, script_hooks, mod = nil)
@@ -131,30 +131,62 @@ module Applitools
131
131
 
132
132
  def prepare_data_for_rg(data)
133
133
  self.all_blobs = data["blobs"]
134
- self.resource_urls = data["resourceUrls"]
134
+ self.resource_urls = data["resourceUrls"].map { |u| URI(u) }
135
135
  self.request_resources = Applitools::Selenium::RenderResources.new
136
+ discovered_resources = []
136
137
 
137
- all_blobs.map { |blob| Applitools::Selenium::VGResource.parse_blob_from_script(blob)}.each do |blob|
138
- request_resources[blob.url] = blob
139
- end
138
+ @discovered_resources_lock = Mutex.new
140
139
 
141
- resource_urls.each do |url|
142
- resource_cache.fetch_and_store(URI(url)) do |s|
143
- resp_proc = proc { |u| server_connector.download_resource(u) }
144
- retry_count = 3
145
- begin
146
- retry_count -= 1
147
- response = resp_proc.call(url)
148
- end while response.status != 200 && retry_count > 0
149
- s.synchronize do
150
- Applitools::Selenium::VGResource.parse_response(url, response)
140
+ fetch_block = proc {}
141
+
142
+ handle_css_block = proc do |urls_to_fetch, url|
143
+ urls_to_fetch.each do |discovered_url|
144
+ target_url = URI.parse(discovered_url)
145
+ unless target_url.host
146
+ target_with_base = url.is_a?(URI) ? url.dup : URI.parse(url)
147
+ target_url = target_with_base.merge target_url
148
+ target_url.freeze
151
149
  end
150
+ next unless /^http/i =~ target_url.scheme
151
+ @discovered_resources_lock.synchronize do
152
+ discovered_resources.push target_url
153
+ end
154
+ resource_cache.fetch_and_store(target_url, &fetch_block)
152
155
  end
153
156
  end
154
157
 
158
+ fetch_block = proc do |_s, key|
159
+ resp_proc = proc { |u| server_connector.download_resource(u) }
160
+ retry_count = 3
161
+ begin
162
+ retry_count -= 1
163
+ response = resp_proc.call(key.dup)
164
+ end while response.status != 200 && retry_count > 0
165
+ Applitools::Selenium::VGResource.parse_response(key.dup, response, on_css_fetched: handle_css_block)
166
+ end
167
+
168
+ blobs = all_blobs.map { |blob| Applitools::Selenium::VGResource.parse_blob_from_script(blob) }.each do |blob|
169
+ request_resources[blob.url] = resource_cache[blob.url] = blob
170
+ end
171
+
172
+ blobs.each do |blob|
173
+ blob.on_css_fetched(handle_css_block)
174
+ blob.lookup_for_resources
175
+ end
176
+
177
+ resource_urls.each do |url|
178
+ resource_cache.fetch_and_store(url, &fetch_block)
179
+ end
180
+
155
181
  resource_urls.each do |u|
156
- key = URI(u)
157
- request_resources[key] = resource_cache[key]
182
+ begin
183
+ request_resources[u] = resource_cache[u]
184
+ rescue Applitools::Selenium::RenderResources
185
+ end
186
+ end
187
+
188
+ discovered_resources.each do |u|
189
+ request_resources[u] = resource_cache[u]
158
190
  end
159
191
 
160
192
  requests = Applitools::Selenium::RenderRequests.new
@@ -178,7 +210,7 @@ module Applitools
178
210
  dom: dom,
179
211
  resources: request_resources,
180
212
  render_info: r_info,
181
- browser: {name: running_test.browser_info.browser_type, platform: running_test.browser_info.platform},
213
+ browser: {xname: running_test.browser_info.browser_type, platform: running_test.browser_info.platform},
182
214
  script_hooks: script_hooks,
183
215
  selectors_to_find_regions_for: region_selectors,
184
216
  send_dom: running_test.eyes.config.send_dom.nil? ? false.to_s : running_test.eyes.config.send_dom.to_s
@@ -2,6 +2,7 @@ require 'thread'
2
2
  module Applitools
3
3
  module Selenium
4
4
  class ResourceCache
5
+ class ResourceMissing < ::Applitools::EyesError; end
5
6
  attr_accessor :cache_map, :semaphore
6
7
 
7
8
  def initialize
@@ -11,7 +12,7 @@ module Applitools
11
12
 
12
13
  def contains?(url)
13
14
  semaphore.synchronize do
14
- cache_map.keys.include?(url) && !cache_map[url].nil?
15
+ check_key(url)
15
16
  end
16
17
  end
17
18
 
@@ -19,8 +20,9 @@ module Applitools
19
20
  current_value = semaphore.synchronize do
20
21
  cache_map[key]
21
22
  end
22
- return current_value unless cache_map[key].is_a? Applitools::Future
23
- update_cache_map(key, cache_map[key].get)
23
+ raise ResourceMissing, key if current_value.nil?
24
+ return current_value unless current_value.is_a? Applitools::Future
25
+ update_cache_map(key, current_value.get)
24
26
  end
25
27
 
26
28
  def []=(key, value)
@@ -30,17 +32,23 @@ module Applitools
30
32
  end
31
33
 
32
34
  def fetch_and_store(key, &block)
33
- return self[key] if self.contains? key
34
- return unless block_given?
35
- self[key] = Applitools::Future.new(semaphore) do |semaphore|
36
- block.call(semaphore)
35
+ semaphore.synchronize do
36
+ return cache_map[key] if check_key(key)
37
+ return unless block_given?
38
+ cache_map[key] = Applitools::Future.new(semaphore) do |semaphore|
39
+ block.call(semaphore, key)
40
+ end
41
+ return true if cache_map[key].is_a? Applitools::Future
42
+ false
37
43
  end
38
- return true if cache_map[key].is_a? Applitools::Future
39
- false
40
44
  end
41
45
 
42
46
  private
43
47
 
48
+ def check_key(url)
49
+ cache_map.keys.include?(url) && !cache_map[url].nil?
50
+ end
51
+
44
52
  def update_cache_map(key, value)
45
53
  semaphore.synchronize do
46
54
  cache_map[key] = value
@@ -39,9 +39,7 @@ module Applitools
39
39
  @semaphore.synchronize do
40
40
  @stopped = true
41
41
  end
42
- @thread_group.list.each do |t|
43
- t.join
44
- end
42
+ @thread_group.list.each(&:join)
45
43
  stopped?
46
44
  end
47
45
 
@@ -81,6 +79,7 @@ module Applitools
81
79
  end
82
80
  end
83
81
  end
82
+ Applitools::EyesLogger.logger.info 'Worker is stopped'
84
83
  rescue => e
85
84
  Applitools::EyesLogger.logger.error "Failed to execute task - #{task_to_run.name}"
86
85
  Applitools::EyesLogger.logger.error e.message
@@ -5,29 +5,41 @@ module Applitools
5
5
  class VGResource
6
6
  include Applitools::Jsonable
7
7
  json_fields :contentType, :hash, :hashFormat
8
- attr_accessor :url, :content
8
+ attr_accessor :url, :content, :handle_css_block
9
9
  alias :content_type :contentType
10
10
  alias :content_type= :contentType=
11
11
 
12
12
  class << self
13
- def parse_blob_from_script(blob)
14
- content = Base64.decode64(blob["value"])
15
- # puts "#{blob['url']} ===> #{blob['type']}"
16
- self.new blob["url"], blob["type"], content
13
+ def parse_blob_from_script(blob, options = {})
14
+ content = Base64.decode64(blob['value'])
15
+ new(blob['url'], blob['type'], content, options)
17
16
  end
18
17
 
19
- def parse_response(url, response)
20
- return self.new(url, 'application/empty-response', '') unless response.status == 200
21
- self.new(url, response.headers['Content-Type'], response.body)
18
+ def parse_response(url, response, options = {})
19
+ return new(url, 'application/empty-response', '') unless response.status == 200
20
+ new(url, response.headers['Content-Type'], response.body, options)
22
21
  end
23
22
  end
24
23
 
25
- def initialize(url, content_type, content)
24
+ def initialize(url, content_type, content, options = {})
25
+ self.handle_css_block = options[:on_css_fetched] if options[:on_css_fetched].is_a? Proc
26
26
  self.url = URI(url)
27
27
  self.content_type = content_type
28
28
  self.content = content
29
29
  self.hash = Digest::SHA256.hexdigest(content)
30
30
  self.hashFormat = 'sha256'
31
+ lookup_for_resources
32
+ end
33
+
34
+ def on_css_fetched(block)
35
+ self.handle_css_block = block
36
+ end
37
+
38
+ def lookup_for_resources
39
+ if %r{^text/css}i =~ content_type && handle_css_block
40
+ parser = Applitools::Selenium::CssParser::FindEmbeddedResources.new(content)
41
+ handle_css_block.call(parser.imported_css + parser.fonts + parser.images, url)
42
+ end
31
43
  end
32
44
 
33
45
  def stringify
@@ -1,4 +1,6 @@
1
1
  require 'applitools/selenium/configuration'
2
+ require 'timeout'
3
+
2
4
  module Applitools
3
5
  module Selenium
4
6
  class VisualGridEyes
@@ -88,30 +90,37 @@ module Applitools
88
90
  END
89
91
  begin
90
92
  sleep wait_before_screenshots
91
-
92
- # script_result = driver.execute_async_script(script).freeze
93
-
94
- dom_snapshot_start_time = Time.now()
95
- result = {}
96
- script_result = nil
97
- loop do
98
- script_result = driver.execute_script(script)
99
- begin
100
- result = Oj.load(script_result)
101
- break if result['status'] == 'SUCCESS'
102
- dom_snapshot_time = Time.now - dom_snapshot_start_time
103
- raise Applitools::EyesError, 'Timeout error while getting dom snapshot!' if dom_snapshot_time > DOM_EXTRACTION_TIMEOUT
104
- rescue Oj::ParseError => e
105
- Applitools::EyesLogger.warn e.message
93
+ Applitools::EyesLogger.info 'Trying to get DOM snapshot...'
94
+
95
+ script_thread = Thread.new do
96
+ result = {}
97
+ while result['status'] != 'SUCCESS'
98
+ Thread.current[:script_result] = driver.execute_script(script)
99
+ begin
100
+ Thread.current[:result] = result = Oj.load(Thread.current[:script_result])
101
+ sleep 0.5
102
+ puts "*"
103
+ rescue Oj::ParseError => e
104
+ Applitools::EyesLogger.warn e.message
105
+ end
106
106
  end
107
107
  end
108
+ sleep 0.5
109
+ script_thread_result = script_thread.join(DOM_EXTRACTION_TIMEOUT)
110
+ raise ::Applitools::EyesError.new 'Timeout error while getting dom snapshot!' unless script_thread_result
111
+ Applitools::EyesLogger.info 'Done!'
112
+
113
+ # require 'pry'
114
+ # binding.pry
115
+ # puts script_thread_result[:result]['value']
108
116
 
109
- mod = Digest::SHA2.hexdigest(script_result)
117
+
118
+ mod = Digest::SHA2.hexdigest(script_thread_result[:script_result])
110
119
 
111
120
  region_x_paths = get_regions_x_paths(target)
112
121
  render_task = RenderTask.new(
113
122
  "Render #{config.short_description} - #{tag}",
114
- result["value"],
123
+ script_thread_result[:result]['value'],
115
124
  visual_grid_manager,
116
125
  server_connector,
117
126
  region_x_paths,
@@ -124,10 +133,12 @@ module Applitools
124
133
  t.check(tag, target, render_task)
125
134
  end
126
135
  test_list.each { |t| t.becomes_not_rendered }
136
+ test_list.each { |t| t.becomes_not_rendered }
127
137
  visual_grid_manager.enqueue_render_task render_task
128
138
  rescue StandardError => e
129
- Applitools::EyesLogger.error e.message
130
139
  test_list.each { |t| t.becomes_tested }
140
+ Applitools::EyesLogger.error e.class.to_s
141
+ Applitools::EyesLogger.error e.message
131
142
  end
132
143
  end
133
144
 
@@ -200,7 +211,7 @@ module Applitools
200
211
  return false if test_list.empty?
201
212
  test_list.each(&:close)
202
213
 
203
- while (!((states = test_list.map(&:state_name).uniq).count == 1 && states.first == :completed)) do
214
+ until ((states = test_list.map(&:state_name).uniq).count == 1 && states.first == :completed) do
204
215
  sleep 0.5
205
216
  end
206
217
  self.opened = false
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Applitools
4
- VERSION = '3.15.29'.freeze
4
+ VERSION = '3.15.30'.freeze
5
5
  end
data/lib/eyes_selenium.rb CHANGED
@@ -22,6 +22,8 @@ Applitools::Selenium.require_dir 'selenium/scripts'
22
22
  Applitools::Selenium.require_dir 'selenium/visual_grid'
23
23
  Applitools::Selenium.require_dir 'selenium'
24
24
  Applitools::Selenium.require_dir 'selenium/dom_capture'
25
+ Applitools::Selenium.require_dir 'selenium/css_parser'
26
+
25
27
 
26
28
  if defined? Selenium::WebDriver::Driver
27
29
  Selenium::WebDriver::Driver.class_eval do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eyes_selenium
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.15.29
4
+ version: 3.15.30
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-08-01 00:00:00.000000000 Z
11
+ date: 2019-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eyes_core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 3.15.29
19
+ version: 3.15.30
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 3.15.29
26
+ version: 3.15.30
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: selenium-webdriver
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: crass
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: state_machine
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -79,6 +93,7 @@ files:
79
93
  - lib/applitools/selenium/browsers_info.rb
80
94
  - lib/applitools/selenium/configuration.rb
81
95
  - lib/applitools/selenium/context_based_scale_provider.rb
96
+ - lib/applitools/selenium/css_parser/find_embedded_resources.rb
82
97
  - lib/applitools/selenium/css_transform/css_transform.rb
83
98
  - lib/applitools/selenium/css_translate_element_position_provider.rb
84
99
  - lib/applitools/selenium/css_translate_position_provider.rb