eyes_selenium 6.12.10 → 6.12.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 +4 -4
- data/CHANGELOG.md +25 -0
- data/eyes_selenium.gemspec +2 -5
- data/lib/applitools/eyes_selenium/version.rb +1 -1
- data/lib/applitools/selenium/browsers_info.rb +2 -0
- data/lib/applitools/selenium/concerns/selenium_eyes.rb +0 -33
- data/lib/applitools/selenium/driver.rb +1 -1
- data/lib/applitools/selenium/eyes.rb +1 -5
- data/lib/applitools/selenium/selenium_eyes.rb +15 -315
- data/lib/applitools/selenium/visual_grid/visual_grid_runner.rb +33 -92
- data/lib/eyes_selenium.rb +0 -2
- metadata +9 -64
- data/lib/applitools/selenium/css_parser/find_embedded_resources.rb +0 -102
- data/lib/applitools/selenium/dom_capture/dom_capture.rb +0 -172
- data/lib/applitools/selenium/dom_capture/dom_capture_script.rb +0 -611
- data/lib/applitools/selenium/external_css_resources.rb +0 -32
- data/lib/applitools/selenium/visual_grid/dom_snapshot_script.rb +0 -198
- data/lib/applitools/selenium/visual_grid/eyes_connector.rb +0 -170
- data/lib/applitools/selenium/visual_grid/render_info.rb +0 -24
- data/lib/applitools/selenium/visual_grid/render_request.rb +0 -24
- data/lib/applitools/selenium/visual_grid/render_requests.rb +0 -12
- data/lib/applitools/selenium/visual_grid/render_task.rb +0 -311
- data/lib/applitools/selenium/visual_grid/resource_cache.rb +0 -69
- data/lib/applitools/selenium/visual_grid/running_test.rb +0 -271
- data/lib/applitools/selenium/visual_grid/thread_pool.rb +0 -95
- data/lib/applitools/selenium/visual_grid/vg_match_window_data.rb +0 -187
- data/lib/applitools/selenium/visual_grid/vg_region.rb +0 -16
- data/lib/applitools/selenium/visual_grid/vg_resource.rb +0 -77
- data/lib/applitools/selenium/visual_grid/vg_task.rb +0 -53
- data/lib/applitools/selenium/visual_grid/visual_grid_eyes.rb +0 -494
- data/lib/applitools/selenium/visual_grid/web_element_region.rb +0 -16
|
@@ -1,110 +1,51 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module Applitools
|
|
3
4
|
module Selenium
|
|
4
|
-
class VisualGridRunner <
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@thread_pool = Applitools::Selenium::VGThreadPool.new(concurrent_open_sessions)
|
|
17
|
-
self.resource_cache = Applitools::Selenium::ResourceCache.new
|
|
18
|
-
self.put_cache = Applitools::Selenium::ResourceCache.new
|
|
19
|
-
init
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def init
|
|
23
|
-
@thread_pool.on_next_task_needed do
|
|
24
|
-
(task = get_task_queue.pop).is_a?(Applitools::Selenium::VGTask) ? task : nil
|
|
5
|
+
class VisualGridRunner < Applitools::EyesRunner
|
|
6
|
+
attr_accessor :all_test_results, :all_pending_exceptions
|
|
7
|
+
attr_reader :test_concurrency
|
|
8
|
+
|
|
9
|
+
DEFAULT_CONCURRENCY = 5
|
|
10
|
+
|
|
11
|
+
def initialize(concurrency_or_options = DEFAULT_CONCURRENCY, mask_log = nil)
|
|
12
|
+
if concurrency_or_options.is_a?(Hash)
|
|
13
|
+
@test_concurrency = concurrency_or_options[:test_concurrency] || DEFAULT_CONCURRENCY
|
|
14
|
+
mask_log = concurrency_or_options[:mask_log]
|
|
15
|
+
else
|
|
16
|
+
@test_concurrency = concurrency_or_options || DEFAULT_CONCURRENCY
|
|
25
17
|
end
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def open(eyes)
|
|
30
|
-
all_eyes << eyes
|
|
18
|
+
super(mask_log)
|
|
19
|
+
self.all_test_results = []
|
|
20
|
+
self.all_pending_exceptions = {}
|
|
31
21
|
end
|
|
32
22
|
|
|
33
|
-
def
|
|
34
|
-
|
|
23
|
+
def aggregate_result(test_result)
|
|
24
|
+
Applitools::ArgumentGuard.is_a?(test_result, 'test_result', Applitools::TestResults)
|
|
25
|
+
all_test_results << test_result
|
|
35
26
|
end
|
|
36
27
|
|
|
37
|
-
def
|
|
38
|
-
|
|
39
|
-
@thread_pool.stop
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def rendering_info(connector)
|
|
43
|
-
@rendering_info ||= connector.rendering_info
|
|
28
|
+
def aggregate_exceptions(result, exception)
|
|
29
|
+
all_pending_exceptions[result] = exception
|
|
44
30
|
end
|
|
45
31
|
|
|
46
32
|
def get_all_test_results(throw_exception = false)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
failed_results.each do |r|
|
|
56
|
-
exception = Applitools::NewTestError.new new_test_error_message(r), r if r.new?
|
|
57
|
-
exception = Applitools::DiffsFoundError.new diffs_found_error_message(r), r if r.unresolved? && !r.new?
|
|
58
|
-
exception = Applitools::TestFailedError.new test_failed_error_message(r), r if r.failed?
|
|
59
|
-
aggregate_exceptions(r, exception)
|
|
33
|
+
begin
|
|
34
|
+
if throw_exception
|
|
35
|
+
all_pending_exceptions.each do |_result, exception|
|
|
36
|
+
raise exception
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
ensure
|
|
40
|
+
delete_all_batches
|
|
60
41
|
end
|
|
61
|
-
|
|
42
|
+
all_universal_results = close_all_eyes
|
|
43
|
+
Applitools::TestResultSummary.new(all_universal_results)
|
|
62
44
|
end
|
|
63
45
|
|
|
64
46
|
def universal_eyes_manager_config
|
|
65
|
-
Applitools::UniversalEyesManagerConfig.vg(
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
private
|
|
69
|
-
|
|
70
|
-
def all_running_tests
|
|
71
|
-
all_eyes.collect(&:test_list).flatten
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def all_running_tests_by_score
|
|
75
|
-
all_running_tests.sort { |x, y| y.score <=> x.score }
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# rubocop:disable Style/AccessorMethodName
|
|
79
|
-
def get_task_queue
|
|
80
|
-
test_to_run = if render_queue.empty?
|
|
81
|
-
all_running_tests_by_score.first
|
|
82
|
-
else
|
|
83
|
-
self
|
|
84
|
-
end
|
|
85
|
-
test_to_run ? test_to_run.queue : EMPTY_QUEUE
|
|
86
|
-
end
|
|
87
|
-
# rubocop:enable Style/AccessorMethodName
|
|
88
|
-
|
|
89
|
-
def new_test_error_message(result)
|
|
90
|
-
original_results = result.original_results
|
|
91
|
-
"New test '#{original_results['name']}' " \
|
|
92
|
-
"of '#{original_results['appName']}' " \
|
|
93
|
-
"Please approve the baseline at #{original_results['appUrls']['session']} "
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def diffs_found_error_message(result)
|
|
97
|
-
original_results = result.original_results
|
|
98
|
-
"Test '#{original_results['name']}' " \
|
|
99
|
-
"of '#{original_results['appname']}' " \
|
|
100
|
-
"detected differences! See details at #{original_results['appUrls']['session']}"
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def test_failed_error_message(result)
|
|
104
|
-
original_results = result.original_results
|
|
105
|
-
"Test '#{original_results['name']}' of '#{original_results['appName']}' " \
|
|
106
|
-
"is failed! See details at #{original_results['appUrls']['session']}"
|
|
47
|
+
Applitools::UniversalEyesManagerConfig.vg(test_concurrency)
|
|
107
48
|
end
|
|
108
49
|
end
|
|
109
50
|
end
|
|
110
|
-
end
|
|
51
|
+
end
|
data/lib/eyes_selenium.rb
CHANGED
|
@@ -45,8 +45,6 @@ Applitools::Selenium.require_dir 'selenium/scripts'
|
|
|
45
45
|
Applitools::Selenium.require_dir 'selenium'
|
|
46
46
|
Applitools::Selenium.require_dir 'eyes_selenium'
|
|
47
47
|
Applitools::Selenium.require_dir 'selenium/visual_grid'
|
|
48
|
-
Applitools::Selenium.require_dir 'selenium/dom_capture'
|
|
49
|
-
Applitools::Selenium.require_dir 'selenium/css_parser'
|
|
50
48
|
|
|
51
49
|
if defined? Selenium::WebDriver::Driver
|
|
52
50
|
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: 6.12.
|
|
4
|
+
version: 6.12.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-
|
|
11
|
+
date: 2025-12-14 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: 6.9.
|
|
19
|
+
version: 6.9.11
|
|
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: 6.9.
|
|
26
|
+
version: 6.9.11
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: selenium-webdriver
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -31,55 +31,19 @@ dependencies:
|
|
|
31
31
|
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '3'
|
|
34
|
-
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - ">="
|
|
34
|
+
- - "<"
|
|
39
35
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: css_parser
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - ">="
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '0'
|
|
36
|
+
version: '5'
|
|
48
37
|
type: :runtime
|
|
49
38
|
prerelease: false
|
|
50
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
40
|
requirements:
|
|
52
41
|
- - ">="
|
|
53
42
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
55
|
-
-
|
|
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'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: state_machines
|
|
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
|
-
- - ">="
|
|
43
|
+
version: '3'
|
|
44
|
+
- - "<"
|
|
81
45
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
46
|
+
version: '5'
|
|
83
47
|
description: Provides SDK for writing Applitools Selenium-based tests
|
|
84
48
|
email:
|
|
85
49
|
- team@applitools.com
|
|
@@ -100,19 +64,15 @@ files:
|
|
|
100
64
|
- lib/applitools/selenium/concerns/selenium_eyes.rb
|
|
101
65
|
- lib/applitools/selenium/configuration.rb
|
|
102
66
|
- lib/applitools/selenium/context_based_scale_provider.rb
|
|
103
|
-
- lib/applitools/selenium/css_parser/find_embedded_resources.rb
|
|
104
67
|
- lib/applitools/selenium/css_transform/css_transform.rb
|
|
105
68
|
- lib/applitools/selenium/css_translate_element_position_provider.rb
|
|
106
69
|
- lib/applitools/selenium/css_translate_position_provider.rb
|
|
107
70
|
- lib/applitools/selenium/device_name_generated.rb
|
|
108
71
|
- lib/applitools/selenium/devices.rb
|
|
109
|
-
- lib/applitools/selenium/dom_capture/dom_capture.rb
|
|
110
|
-
- lib/applitools/selenium/dom_capture/dom_capture_script.rb
|
|
111
72
|
- lib/applitools/selenium/driver.rb
|
|
112
73
|
- lib/applitools/selenium/element.rb
|
|
113
74
|
- lib/applitools/selenium/element_position_provider.rb
|
|
114
75
|
- lib/applitools/selenium/entire_element_screenshot.rb
|
|
115
|
-
- lib/applitools/selenium/external_css_resources.rb
|
|
116
76
|
- lib/applitools/selenium/eyes.rb
|
|
117
77
|
- lib/applitools/selenium/eyes_screenshot.rb
|
|
118
78
|
- lib/applitools/selenium/eyes_target_locator.rb
|
|
@@ -147,29 +107,14 @@ files:
|
|
|
147
107
|
- lib/applitools/selenium/visual_grid/android_multi_device_target.rb
|
|
148
108
|
- lib/applitools/selenium/visual_grid/chrome_emulation_info.rb
|
|
149
109
|
- lib/applitools/selenium/visual_grid/desktop_browser_info.rb
|
|
150
|
-
- lib/applitools/selenium/visual_grid/dom_snapshot_script.rb
|
|
151
110
|
- lib/applitools/selenium/visual_grid/emulation_base_info.rb
|
|
152
|
-
- lib/applitools/selenium/visual_grid/eyes_connector.rb
|
|
153
111
|
- lib/applitools/selenium/visual_grid/i_render_browser_info.rb
|
|
154
112
|
- lib/applitools/selenium/visual_grid/ios_device_info.rb
|
|
155
113
|
- lib/applitools/selenium/visual_grid/ios_device_name.rb
|
|
156
114
|
- lib/applitools/selenium/visual_grid/ios_device_name_generated.rb
|
|
157
115
|
- lib/applitools/selenium/visual_grid/ios_multi_device_target.rb
|
|
158
116
|
- lib/applitools/selenium/visual_grid/render_browser_info.rb
|
|
159
|
-
- lib/applitools/selenium/visual_grid/render_info.rb
|
|
160
|
-
- lib/applitools/selenium/visual_grid/render_request.rb
|
|
161
|
-
- lib/applitools/selenium/visual_grid/render_requests.rb
|
|
162
|
-
- lib/applitools/selenium/visual_grid/render_task.rb
|
|
163
|
-
- lib/applitools/selenium/visual_grid/resource_cache.rb
|
|
164
|
-
- lib/applitools/selenium/visual_grid/running_test.rb
|
|
165
|
-
- lib/applitools/selenium/visual_grid/thread_pool.rb
|
|
166
|
-
- lib/applitools/selenium/visual_grid/vg_match_window_data.rb
|
|
167
|
-
- lib/applitools/selenium/visual_grid/vg_region.rb
|
|
168
|
-
- lib/applitools/selenium/visual_grid/vg_resource.rb
|
|
169
|
-
- lib/applitools/selenium/visual_grid/vg_task.rb
|
|
170
|
-
- lib/applitools/selenium/visual_grid/visual_grid_eyes.rb
|
|
171
117
|
- lib/applitools/selenium/visual_grid/visual_grid_runner.rb
|
|
172
|
-
- lib/applitools/selenium/visual_grid/web_element_region.rb
|
|
173
118
|
- lib/eyes_selenium.rb
|
|
174
119
|
homepage: https://www.applitools.com
|
|
175
120
|
licenses:
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'crass'
|
|
4
|
-
|
|
5
|
-
module Applitools
|
|
6
|
-
module Selenium
|
|
7
|
-
module CssParser
|
|
8
|
-
class FindEmbeddedResources
|
|
9
|
-
class << self
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
class CssParseError < Applitools::EyesError; end
|
|
13
|
-
|
|
14
|
-
attr_accessor :css
|
|
15
|
-
|
|
16
|
-
def initialize(css)
|
|
17
|
-
self.css = css
|
|
18
|
-
@nodes_by_type = {}
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def imported_css
|
|
22
|
-
fetch_urls(import_rules)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def fonts
|
|
26
|
-
fetch_urls(font_face_rules)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def images
|
|
30
|
-
fetch_urls(images_rules)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
def url(node)
|
|
36
|
-
result = []
|
|
37
|
-
node[:tokens].select { |t| t[:node] == :url }.uniq.each do |nd|
|
|
38
|
-
result << nd[:value] if nd && !nd.empty?
|
|
39
|
-
end
|
|
40
|
-
node[:tokens].select { |t| t[:node] == :function && t[:value] == 'url' }.uniq.each do |nd|
|
|
41
|
-
url_index = node[:tokens].index(nd)
|
|
42
|
-
url_string_node = url_index && node[:tokens][url_index + 1]
|
|
43
|
-
result << (
|
|
44
|
-
url_string_node && url_string_node[:node] == :string &&
|
|
45
|
-
!url_string_node[:value].empty? && url_string_node[:value]
|
|
46
|
-
)
|
|
47
|
-
end
|
|
48
|
-
result.compact
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def fetch_urls(nodes)
|
|
52
|
-
nodes.map { |n| url(n) }.flatten.compact
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def import_rules
|
|
56
|
-
# css_nodes.select { |n| n[:node] == :at_rule && n[:name] == 'import' }
|
|
57
|
-
nodes_by_type[:import_rules]
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def font_face_rules
|
|
61
|
-
# css_nodes.select { |n| n[:node] == :at_rule && n[:name] == 'font-face' }
|
|
62
|
-
nodes_by_type[:font_face_rules]
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def images_rules
|
|
66
|
-
# css_nodes.select { |n| n[:node] == :style_rule }.map { |n| n[:children] }
|
|
67
|
-
# .flatten
|
|
68
|
-
# .select { |n| n[:node] == :property && (n[:name] == 'background' || n[:name] == 'background-image') }
|
|
69
|
-
nodes_by_type[:images_rules]
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def css_nodes
|
|
73
|
-
@css_nodes ||= parse_nodes
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def nodes_by_type
|
|
77
|
-
return @nodes_by_type unless @nodes_by_type.empty?
|
|
78
|
-
@nodes_by_type[:import_rules] ||= []
|
|
79
|
-
@nodes_by_type[:font_face_rules] ||= []
|
|
80
|
-
@nodes_by_type[:images_rules] ||= []
|
|
81
|
-
css_nodes.each do |n|
|
|
82
|
-
@nodes_by_type[:import_rules] << n if n[:node] == :at_rule && n[:name] == 'import'
|
|
83
|
-
@nodes_by_type[:font_face_rules] << n if n[:node] == :at_rule && n[:name] == 'font-face'
|
|
84
|
-
@nodes_by_type[:images_rules] << n if n[:node] == :style_rule
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
unless @nodes_by_type[:images_rules].nil?
|
|
88
|
-
@nodes_by_type[:images_rules].map! { |n| n[:children] }.flatten!
|
|
89
|
-
@nodes_by_type[:images_rules] = @nodes_by_type[:images_rules].select do |n|
|
|
90
|
-
n[:node] == :property && (n[:name] == 'background' || n[:name] == 'background-image')
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
@nodes_by_type
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def parse_nodes
|
|
97
|
-
Crass.parse css
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Applitools
|
|
4
|
-
module Selenium
|
|
5
|
-
module DomCapture
|
|
6
|
-
extend self
|
|
7
|
-
DOM_EXTRACTION_TIMEOUT = 300 # seconds
|
|
8
|
-
def full_window_dom(driver, server_connector, logger, position_provider = nil)
|
|
9
|
-
return get_dom(driver, server_connector, logger) unless position_provider
|
|
10
|
-
scroll_top_and_return_back(position_provider) do
|
|
11
|
-
get_dom(driver, server_connector, logger)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def get_dom(driver, server_connector, logger)
|
|
16
|
-
original_frame_chain = driver.frame_chain
|
|
17
|
-
dom = get_frame_dom(driver, server_connector, logger)
|
|
18
|
-
unless original_frame_chain.empty?
|
|
19
|
-
driver.switch_to.default_content
|
|
20
|
-
driver.switch_to.frames(frame_chain: original_frame_chain)
|
|
21
|
-
end
|
|
22
|
-
# CSS processing
|
|
23
|
-
dom
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def get_frame_dom(driver, server_connector, logger)
|
|
27
|
-
logger.info 'Trying to get DOM from driver'
|
|
28
|
-
start_time = Time.now
|
|
29
|
-
script_response = nil
|
|
30
|
-
loop do
|
|
31
|
-
result_as_string = driver.execute_script(CAPTURE_FRAME_SCRIPT + ' return __captureDomAndPoll();')
|
|
32
|
-
script_response = Oj.load(result_as_string)
|
|
33
|
-
status = script_response['status']
|
|
34
|
-
break if status == 'SUCCESS'
|
|
35
|
-
raise Applitools::EyesError, 'DOM extraction timeout!' if Time.now - start_time > DOM_EXTRACTION_TIMEOUT
|
|
36
|
-
raise Applitools::EyesError, "DOM extraction error: #{script_response['error']}" if script_response['error']
|
|
37
|
-
sleep(0.2)
|
|
38
|
-
end
|
|
39
|
-
response_lines = script_response['value'].split(/\r?\n/)
|
|
40
|
-
separators = Oj.load(response_lines.shift)
|
|
41
|
-
missing_css_list = []
|
|
42
|
-
missing_frame_list = []
|
|
43
|
-
data = []
|
|
44
|
-
|
|
45
|
-
blocks = DomParts.new(missing_css_list, missing_frame_list, data)
|
|
46
|
-
collector = blocks.collectors.next
|
|
47
|
-
response_lines.each do |line|
|
|
48
|
-
if line == separators['separator']
|
|
49
|
-
collector = blocks.collectors.next
|
|
50
|
-
else
|
|
51
|
-
collector << line
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
logger.info "Missing CSS: #{missing_css_list.count}"
|
|
55
|
-
logger.info "Missing frames: #{missing_frame_list.count}"
|
|
56
|
-
|
|
57
|
-
frame_data = recurse_frames(driver, server_connector, logger, missing_frame_list)
|
|
58
|
-
result = replace(separators['iframeStartToken'], separators['iframeEndToken'], data.first, frame_data)
|
|
59
|
-
css_data = fetch_css_files(missing_css_list, server_connector)
|
|
60
|
-
replace(separators['cssStartToken'], separators['cssEndToken'], result, css_data)
|
|
61
|
-
rescue StandardError => e
|
|
62
|
-
logger.error(e.class)
|
|
63
|
-
logger.error(e.message)
|
|
64
|
-
return ''
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def fetch_css_files(missing_css_list, server_connector)
|
|
68
|
-
result = {}
|
|
69
|
-
missing_css_list.each do |url|
|
|
70
|
-
next if url.empty?
|
|
71
|
-
next if /^blob:/ =~ url
|
|
72
|
-
|
|
73
|
-
begin
|
|
74
|
-
missing_css_response = server_connector.download_resource(
|
|
75
|
-
url,
|
|
76
|
-
Applitools::Utils::EyesSeleniumUtils.user_agent(driver)
|
|
77
|
-
)
|
|
78
|
-
response_headers = missing_css_response.headers
|
|
79
|
-
raise Applitools::EyesError, "Wrong response header: #{response_headers['content-type']}" unless
|
|
80
|
-
%r{^text/css.*}i =~ response_headers['content-type']
|
|
81
|
-
|
|
82
|
-
css = missing_css_response.body
|
|
83
|
-
|
|
84
|
-
found_and_missing_css =
|
|
85
|
-
Applitools::Selenium::CssParser::FindEmbeddedResources.new(css).imported_css.map do |found_url|
|
|
86
|
-
base_url(url).merge(found_url).to_s
|
|
87
|
-
end
|
|
88
|
-
fetch_css_files(found_and_missing_css, server_connector).each do |_k, v|
|
|
89
|
-
css += v
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
result[url] = Oj.dump("\n/** #{url} **/\n" + css).gsub(/^\"|\"$/, '')
|
|
93
|
-
rescue StandardError
|
|
94
|
-
result[url] = ''
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
result
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def recurse_frames(driver, server_connector, logger, missing_frame_list)
|
|
101
|
-
return if missing_frame_list.empty?
|
|
102
|
-
frame_data = {}
|
|
103
|
-
frame_chain = driver.frame_chain
|
|
104
|
-
origin_location = driver.execute_script('return document.location.href')
|
|
105
|
-
missing_frame_list.each do |missing_frame_line|
|
|
106
|
-
logger.info "Switching to frame line: #{missing_frame_line}"
|
|
107
|
-
missing_frame_line.split(/,/).each do |xpath|
|
|
108
|
-
logger.info "switching to specific frame: #{xpath}"
|
|
109
|
-
begin
|
|
110
|
-
frame_element = driver.find_element(:xpath, xpath)
|
|
111
|
-
frame_src = frame_element.attribute('src')
|
|
112
|
-
driver.switch_to.frame(frame_element)
|
|
113
|
-
logger.info "Switched to frame ( #{xpath} ) with src( #{frame_src} )"
|
|
114
|
-
ensure
|
|
115
|
-
location_after_switch = driver.execute_script('return document.location.href')
|
|
116
|
-
|
|
117
|
-
if origin_location == location_after_switch
|
|
118
|
-
logger.info "Switch to frame (#{missing_frame_line}) failed"
|
|
119
|
-
frame_data[missing_frame_line] = ''
|
|
120
|
-
else
|
|
121
|
-
result = get_frame_dom(driver, server_connector, logger)
|
|
122
|
-
frame_data[missing_frame_line] = result
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
driver.switch_to.default_content
|
|
126
|
-
driver.switch_to.frames(frame_chain: frame_chain)
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
frame_data
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def scroll_top_and_return_back(position_provider)
|
|
134
|
-
original_position = position_provider.current_position
|
|
135
|
-
return yield if block_given? && original_position.nil?
|
|
136
|
-
position_provider.scroll_to Applitools::Location.new(0, 0)
|
|
137
|
-
result = yield if block_given?
|
|
138
|
-
position_provider.scroll_to original_position
|
|
139
|
-
result
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def replace(open_token, close_token, input, replacements)
|
|
143
|
-
pattern = /#{open_token}(?<key>.+?)#{close_token}/
|
|
144
|
-
input.gsub(pattern) { |_m| replacements[Regexp.last_match(1)] }
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def base_url(url)
|
|
148
|
-
uri = URI.parse(url)
|
|
149
|
-
uri.query = uri.fragment = nil
|
|
150
|
-
uri.path = ''
|
|
151
|
-
uri
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
class DomParts
|
|
155
|
-
attr_accessor :dom_part_collectors
|
|
156
|
-
def initialize(*args)
|
|
157
|
-
self.dom_part_collectors = args
|
|
158
|
-
@index = 0
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def collectors
|
|
162
|
-
@collectors ||= Enumerator.new(dom_part_collectors.length) do |y|
|
|
163
|
-
loop do
|
|
164
|
-
y << dom_part_collectors[@index]
|
|
165
|
-
@index += 1
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
end
|