eyes_selenium 3.15.29 → 3.15.30

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