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.
- checksums.yaml +4 -4
- data/lib/applitools/selenium/css_parser/find_embedded_resources.rb +69 -0
- data/lib/applitools/selenium/dom_capture/dom_capture.rb +148 -94
- data/lib/applitools/selenium/dom_capture/dom_capture_script.rb +448 -89
- data/lib/applitools/selenium/render_resources.rb +5 -4
- data/lib/applitools/selenium/selenium_eyes.rb +1 -1
- data/lib/applitools/selenium/visual_grid/render_task.rb +50 -18
- data/lib/applitools/selenium/visual_grid/resource_cache.rb +17 -9
- data/lib/applitools/selenium/visual_grid/thread_pool.rb +2 -3
- data/lib/applitools/selenium/visual_grid/vg_resource.rb +21 -9
- data/lib/applitools/selenium/visual_grid/visual_grid_eyes.rb +30 -19
- data/lib/applitools/version.rb +1 -1
- data/lib/eyes_selenium.rb +2 -0
- metadata +19 -4
@@ -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
|
8
|
-
" (but got #{value.class})" unless value.is_a? Applitools::Selenium::VGResource
|
9
|
-
|
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.
|
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
|
-
|
138
|
-
request_resources[blob.url] = blob
|
139
|
-
end
|
138
|
+
@discovered_resources_lock = Mutex.new
|
140
139
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
157
|
-
|
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: {
|
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
|
-
|
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
|
-
|
23
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
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[
|
15
|
-
|
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
|
21
|
-
|
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
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
-
|
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[
|
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
|
-
|
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
|
data/lib/applitools/version.rb
CHANGED
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.
|
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-
|
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.
|
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.
|
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
|