eyes_selenium 3.14.10 → 3.15.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/applitools/selenium/concerns/browser_types.rb +15 -0
- data/lib/applitools/selenium/concerns/browsers_info.rb +16 -0
- data/lib/applitools/selenium/concerns/external_css_resources.rb +31 -0
- data/lib/applitools/selenium/concerns/render_browser_info_fluent.rb +42 -0
- data/lib/applitools/selenium/concerns/render_resources.rb +15 -0
- data/lib/applitools/selenium/concerns/rgrid_dom.rb +46 -0
- data/lib/applitools/selenium/concerns/stitch_modes.rb +15 -0
- data/lib/applitools/selenium/concerns/test_list.rb +23 -0
- data/lib/applitools/selenium/eyes.rb +13 -854
- data/lib/applitools/selenium/scripts/process_page_and_serialize.rb +519 -0
- data/lib/applitools/selenium/selenium_configuration.rb +64 -0
- data/lib/applitools/selenium/selenium_eyes.rb +860 -0
- data/lib/applitools/selenium/target.rb +2 -2
- data/lib/applitools/selenium/visual_grid/eyes_connector.rb +170 -0
- data/lib/applitools/selenium/visual_grid/render_browser_info.rb +31 -0
- data/lib/applitools/selenium/visual_grid/render_info.rb +9 -0
- data/lib/applitools/selenium/visual_grid/render_request.rb +22 -0
- data/lib/applitools/selenium/visual_grid/render_requests.rb +11 -0
- data/lib/applitools/selenium/visual_grid/render_task.rb +171 -0
- data/lib/applitools/selenium/visual_grid/resource_cache.rb +51 -0
- data/lib/applitools/selenium/visual_grid/running_test.rb +198 -0
- data/lib/applitools/selenium/visual_grid/thread_pool.rb +94 -0
- data/lib/applitools/selenium/visual_grid/vg_resource.rb +37 -0
- data/lib/applitools/selenium/visual_grid/vg_task.rb +46 -0
- data/lib/applitools/selenium/visual_grid/visual_grid_eyes.rb +236 -0
- data/lib/applitools/selenium/visual_grid/visual_grid_runner.rb +57 -0
- data/lib/applitools/version.rb +1 -1
- data/lib/eyes_selenium.rb +3 -0
- metadata +46 -7
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'state_machine'
|
2
|
+
require 'digest'
|
3
|
+
|
4
|
+
module Applitools
|
5
|
+
module Selenium
|
6
|
+
class RunningTest
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
|
9
|
+
|
10
|
+
state_machine :initial => :new do
|
11
|
+
state :new do
|
12
|
+
def close
|
13
|
+
becomes_completed
|
14
|
+
end
|
15
|
+
|
16
|
+
def score
|
17
|
+
0
|
18
|
+
end
|
19
|
+
|
20
|
+
def queue
|
21
|
+
Applitools::Selenium::VisualGridRunner::EMPTY_QUEUE
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
state :not_rendered do
|
26
|
+
def score
|
27
|
+
render_queue.length * 10
|
28
|
+
end
|
29
|
+
|
30
|
+
def queue
|
31
|
+
render_queue
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
state :opened do
|
36
|
+
def score
|
37
|
+
task_queue.length
|
38
|
+
end
|
39
|
+
|
40
|
+
def queue
|
41
|
+
return Applitools::Selenium::VisualGridRunner::EMPTY_QUEUE unless task_lock.nil?
|
42
|
+
self.task_lock = task_queue.last unless task_queue.last.nil?
|
43
|
+
task_queue
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
state :rendered do
|
48
|
+
def score
|
49
|
+
open_queue.length
|
50
|
+
end
|
51
|
+
|
52
|
+
def queue
|
53
|
+
open_queue
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
state :tested do
|
58
|
+
def score
|
59
|
+
close_queue.length
|
60
|
+
end
|
61
|
+
|
62
|
+
def queue
|
63
|
+
close_queue
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
state :completed do
|
68
|
+
def score
|
69
|
+
0
|
70
|
+
end
|
71
|
+
|
72
|
+
def queue
|
73
|
+
Applitools::Selenium::VisualGridRunner::EMPTY_QUEUE
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
state :new, :not_rendered, :opened, :rendered, :tested do
|
78
|
+
def close
|
79
|
+
self.test_result = nil
|
80
|
+
close_task = Applitools::Selenium::VGTask.new("close #{browser_info}") do
|
81
|
+
eyes.close(false)
|
82
|
+
end
|
83
|
+
close_task.on_task_succeeded do |task_result|
|
84
|
+
self.test_result = task_result
|
85
|
+
end.on_task_error do |e|
|
86
|
+
self.pending_exceptions << e
|
87
|
+
end.on_task_completed do
|
88
|
+
watch_close[close_task] = true
|
89
|
+
becomes_completed if all_tasks_completed?(watch_close)
|
90
|
+
end
|
91
|
+
close_queue << close_task
|
92
|
+
watch_close[close_task] = false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
event :becomes_not_rendered do
|
97
|
+
transition :new => :not_rendered
|
98
|
+
end
|
99
|
+
|
100
|
+
event :becomes_opened do
|
101
|
+
transition :rendered => :opened
|
102
|
+
end
|
103
|
+
|
104
|
+
event :becomes_rendered do
|
105
|
+
transition :not_rendered => :rendered
|
106
|
+
end
|
107
|
+
|
108
|
+
event :becomes_tested do
|
109
|
+
transition :opened => :tested
|
110
|
+
end
|
111
|
+
|
112
|
+
event :becomes_completed do
|
113
|
+
transition [:not_rendered, :rendered, :opened, :tested] => :completed
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
attr_accessor :open_queue, :task_queue, :render_queue, :close_queue, :watch_open, :watch_task, :watch_render, :watch_close
|
118
|
+
|
119
|
+
attr_accessor :eyes, :browser_info, :test_result, :pending_exceptions, :driver, :task_lock
|
120
|
+
|
121
|
+
def initialize(eyes, browser_info, driver)
|
122
|
+
Applitools::ArgumentGuard.is_a? eyes, 'eyes', Applitools::Selenium::EyesConnector
|
123
|
+
Applitools::ArgumentGuard.is_a? browser_info, 'browser_info', Applitools::Selenium::RenderBrowserInfo
|
124
|
+
|
125
|
+
self.eyes = eyes
|
126
|
+
self.browser_info = browser_info
|
127
|
+
self.driver = driver
|
128
|
+
|
129
|
+
self.open_queue = []
|
130
|
+
self.task_queue = []
|
131
|
+
self.render_queue = []
|
132
|
+
self.close_queue = []
|
133
|
+
|
134
|
+
self.watch_open = {}
|
135
|
+
self.watch_task = {}
|
136
|
+
self.watch_render = {}
|
137
|
+
self.watch_close = {}
|
138
|
+
|
139
|
+
self.task_lock = nil
|
140
|
+
|
141
|
+
self.pending_exceptions = []
|
142
|
+
super()
|
143
|
+
init
|
144
|
+
end
|
145
|
+
|
146
|
+
def init
|
147
|
+
open_task = Applitools::Selenium::VGTask.new("open #{browser_info}") { eyes.open(driver, browser_info) }
|
148
|
+
|
149
|
+
open_task.on_task_succeeded { watch_open[open_task] = true; becomes_opened if all_tasks_completed?(watch_open) }.
|
150
|
+
on_task_error { |e| pending_exceptions << e; becomes_completed }
|
151
|
+
open_queue << open_task
|
152
|
+
watch_open[open_task] = false
|
153
|
+
end
|
154
|
+
|
155
|
+
def check(tag, target, script_result, visual_grid_manager, mod = nil)
|
156
|
+
render_task = RenderTask.new(
|
157
|
+
"Render #{eyes.config.short_description} - #{tag}",
|
158
|
+
script_result,
|
159
|
+
self,
|
160
|
+
visual_grid_manager.resource_cache,
|
161
|
+
visual_grid_manager.put_cache,
|
162
|
+
visual_grid_manager.rendering_info(eyes.server_connector),
|
163
|
+
eyes.server_connector,
|
164
|
+
mod
|
165
|
+
)
|
166
|
+
|
167
|
+
check_task = VGTask.new("perform check #{tag} #{target}") do
|
168
|
+
eyes.check(tag, target, render_task.uuid)
|
169
|
+
end
|
170
|
+
|
171
|
+
check_task.on_task_completed do
|
172
|
+
watch_task[check_task] = true
|
173
|
+
self.task_lock = nil if task_lock.uuid == check_task.uuid
|
174
|
+
becomes_tested if all_tasks_completed?(watch_task)
|
175
|
+
end
|
176
|
+
|
177
|
+
task_queue.insert(0, check_task)
|
178
|
+
watch_task[check_task] = false
|
179
|
+
|
180
|
+
render_task.on_task_succeeded do |r|
|
181
|
+
eyes.render_status_for_task(render_task.uuid, r) if r
|
182
|
+
watch_render[render_task] = true
|
183
|
+
becomes_rendered if all_tasks_completed?(watch_render)
|
184
|
+
end.on_task_error do
|
185
|
+
becomes_completed
|
186
|
+
end
|
187
|
+
render_queue << render_task
|
188
|
+
watch_render[render_task] = false
|
189
|
+
end
|
190
|
+
|
191
|
+
def all_tasks_completed?(watch)
|
192
|
+
return true if state_name == :completed
|
193
|
+
uniq_values = watch.values.uniq
|
194
|
+
uniq_values.count == 1 && uniq_values.first == true
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Applitools
|
4
|
+
module Selenium
|
5
|
+
class VGThreadPool
|
6
|
+
extend Forwardable
|
7
|
+
attr_accessor :concurrency
|
8
|
+
def_delegator 'Applitools::EyesLogger', :logger
|
9
|
+
|
10
|
+
def initialize(concurrency = 10)
|
11
|
+
self.concurrency = concurrency
|
12
|
+
@stopped = true
|
13
|
+
@thread_group = ThreadGroup.new
|
14
|
+
@semaphore = Mutex.new
|
15
|
+
@next_task_block = nil
|
16
|
+
@watchdog = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_next_task_needed(&block)
|
20
|
+
@next_task_block = block if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
def start
|
24
|
+
@semaphore.synchronize { @stopped = false }
|
25
|
+
init_or_renew_threads
|
26
|
+
@watchdog = Thread.new do
|
27
|
+
catch(:exit) do
|
28
|
+
loop do
|
29
|
+
throw :exit if stopped?
|
30
|
+
sleep 5
|
31
|
+
init_or_renew_threads
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def stop
|
38
|
+
@watchdog.exit
|
39
|
+
@semaphore.synchronize do
|
40
|
+
@stopped = true
|
41
|
+
end
|
42
|
+
@thread_group.list.each do |t|
|
43
|
+
t.join
|
44
|
+
end
|
45
|
+
stopped?
|
46
|
+
end
|
47
|
+
|
48
|
+
def stopped?
|
49
|
+
@semaphore.synchronize { @stopped }
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def next_task
|
55
|
+
@semaphore.synchronize do
|
56
|
+
return @next_task_block.call if @next_task_block && @next_task_block.respond_to?(:call)
|
57
|
+
end
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def init_or_renew_threads
|
62
|
+
(concurrency - @thread_group.list.count).times do
|
63
|
+
logger.debug 'starting new thread (task worker)'
|
64
|
+
next_thread
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def next_thread
|
69
|
+
thread = Thread.new do
|
70
|
+
begin
|
71
|
+
catch(:exit) do
|
72
|
+
loop do
|
73
|
+
throw :exit if stopped?
|
74
|
+
task_to_run = next_task
|
75
|
+
if task_to_run && task_to_run.respond_to?(:call)
|
76
|
+
logger.debug "Executing new task... #{task_to_run.name}"
|
77
|
+
task_to_run.call
|
78
|
+
logger.debug 'Done!'
|
79
|
+
else
|
80
|
+
sleep 0.5
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
rescue => e
|
85
|
+
Applitools::EyesLogger.logger.error "Failed to execute task - #{task_to_run.name}"
|
86
|
+
Applitools::EyesLogger.logger.error e.message
|
87
|
+
Applitools::EyesLogger.logger.error e.backtrace.join( ' ')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
@thread_group.add thread
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'digest'
|
3
|
+
module Applitools
|
4
|
+
module Selenium
|
5
|
+
class VGResource
|
6
|
+
include Applitools::Jsonable
|
7
|
+
json_fields :contentType, :hash, :hashFormat
|
8
|
+
attr_accessor :url, :content
|
9
|
+
alias :content_type :contentType
|
10
|
+
alias :content_type= :contentType=
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def parse_blob_from_script(blob)
|
14
|
+
content = Base64.decode64(blob["value"])
|
15
|
+
self.new blob["url"], blob["type"], content
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_response(url, response)
|
19
|
+
return self.new(url, 'application/empty-response', '') unless response.status == 200
|
20
|
+
self.new(url, response.headers['Content-Type'], response.body)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(url, content_type, content)
|
25
|
+
self.url = URI(url)
|
26
|
+
self.content_type = content_type
|
27
|
+
self.content = content
|
28
|
+
self.hash = Digest::SHA256.hexdigest(content)
|
29
|
+
self.hashFormat = 'sha256'
|
30
|
+
end
|
31
|
+
|
32
|
+
def stringify
|
33
|
+
url.to_s + content_type.to_s + hash
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
module Applitools
|
3
|
+
module Selenium
|
4
|
+
class VGTask
|
5
|
+
attr_accessor :name, :uuid
|
6
|
+
def initialize(name, &block)
|
7
|
+
self.name = name
|
8
|
+
@block_to_run = block if block_given?
|
9
|
+
@callback = nil
|
10
|
+
@error_callback = nil
|
11
|
+
@completed_callback = nil
|
12
|
+
self.uuid = SecureRandom.uuid
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_task_succeeded(&block)
|
16
|
+
@callback = block if block_given?
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_task_error(&block)
|
21
|
+
@error_callback = block if block_given?
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_task_completed(&block)
|
26
|
+
@completed_callback = block if block_given?
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def call
|
31
|
+
return unless @block_to_run.respond_to? :call
|
32
|
+
begin
|
33
|
+
res = @block_to_run.call
|
34
|
+
@callback.call(res) if @callback.respond_to? :call
|
35
|
+
rescue StandardError => e
|
36
|
+
Applitools::EyesLogger.logger.error 'Failed to execute task!'
|
37
|
+
Applitools::EyesLogger.logger.error e.message
|
38
|
+
Applitools::EyesLogger.logger.error e.backtrace.join('\n\t')
|
39
|
+
@error_callback.call(e) if @error_callback.respond_to? :call
|
40
|
+
ensure
|
41
|
+
@completed_callback.call if @completed_callback.respond_to? :call
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'applitools/selenium/selenium_configuration'
|
2
|
+
module Applitools
|
3
|
+
module Selenium
|
4
|
+
class VisualGridEyes
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
|
8
|
+
|
9
|
+
attr_accessor :visual_grid_manager, :driver, :current_url, :current_config, :fetched_cache_map, :config
|
10
|
+
attr_accessor :test_list
|
11
|
+
|
12
|
+
attr_accessor :api_key, :server_url, :proxy, :opened
|
13
|
+
|
14
|
+
def_delegators 'config', *Applitools::Selenium::SeleniumConfiguration.methods_to_delegate
|
15
|
+
def_delegators 'config', *Applitools::EyesBaseConfiguration.methods_to_delegate
|
16
|
+
|
17
|
+
def initialize(visual_grid_manager, server_url = nil)
|
18
|
+
ensure_config
|
19
|
+
self.visual_grid_manager = visual_grid_manager
|
20
|
+
self.test_list = Applitools::Selenium::TestList.new
|
21
|
+
self.opened = false
|
22
|
+
end
|
23
|
+
|
24
|
+
def ensure_config
|
25
|
+
self.config = Applitools::Selenium::SeleniumConfiguration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def open(*args)
|
30
|
+
self.test_list = Applitools::Selenium::TestList.new
|
31
|
+
options = Applitools::Utils.extract_options!(args)
|
32
|
+
Applitools::ArgumentGuard.hash(options, 'options', [:driver])
|
33
|
+
|
34
|
+
# self.current_config = options.delete(:config)
|
35
|
+
# self.current_config = yield(Applitools::Selenium::SeleniumConfiguration.new) if block_given?
|
36
|
+
|
37
|
+
# Applitools::ArgumentGuard.is_a? options[:driver], 'options[:driver]', ::Selenium::WebDriver
|
38
|
+
# Applitools::ArgumentGuard.is_a? current_config, 'options[:config]', Applitools::Selenium::SeleniumConfiguration
|
39
|
+
|
40
|
+
# batch_info.name = config.app_name
|
41
|
+
self.driver = options.delete(:driver)
|
42
|
+
self.current_url = driver.current_url
|
43
|
+
|
44
|
+
visual_grid_manager.open(self)
|
45
|
+
|
46
|
+
logger.info("getting all browsers info...")
|
47
|
+
browsers_info_list = config.browsers_info
|
48
|
+
logger.info("creating test descriptors for each browser info...")
|
49
|
+
browsers_info_list.each do |bi|
|
50
|
+
test_list.push Applitools::Selenium::RunningTest.new(eyes_connector, bi, driver)
|
51
|
+
end
|
52
|
+
self.opened = true
|
53
|
+
driver
|
54
|
+
end
|
55
|
+
|
56
|
+
def eyes_connector
|
57
|
+
logger.info("creating VisualGridEyes server connector")
|
58
|
+
::Applitools::Selenium::EyesConnector.new(server_url).tap do |connector|
|
59
|
+
connector.batch = batch_info
|
60
|
+
connector.config = config.deep_clone
|
61
|
+
connector.proxy = proxy if proxy.is_a? Applitools::Connectivity::Proxy
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def check(tag, target)
|
66
|
+
script = <<-END
|
67
|
+
var callback = arguments[arguments.length - 1]; return (#{Applitools::Selenium::Scripts::PROCESS_RESOURCES})().then(JSON.stringify).then(callback, function(err) {callback(err.stack || err.toString())});
|
68
|
+
END
|
69
|
+
|
70
|
+
script_result = driver.execute_async_script(script).freeze
|
71
|
+
mod = Digest::SHA2.hexdigest(script_result)
|
72
|
+
test_list.each do |test|
|
73
|
+
test.check(tag, target, script_result.dup, visual_grid_manager, mod)
|
74
|
+
end
|
75
|
+
test_list.each { |t| t.becomes_not_rendered}
|
76
|
+
end
|
77
|
+
|
78
|
+
def close(throw_exception = true)
|
79
|
+
return false if test_list.empty?
|
80
|
+
test_list.each do |t|
|
81
|
+
t.close
|
82
|
+
end
|
83
|
+
|
84
|
+
while (!((states = test_list.map(&:state_name).uniq).count == 1 && states.first == :completed)) do
|
85
|
+
sleep 0.5
|
86
|
+
end
|
87
|
+
self.opened = false
|
88
|
+
|
89
|
+
test_list.select { |t| t.pending_exceptions && !t.pending_exceptions.empty? }.each do |t|
|
90
|
+
t.pending_exceptions.each do |e|
|
91
|
+
raise e
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
if throw_exception
|
96
|
+
test_list.map(&:test_result).compact.each do |r|
|
97
|
+
raise Applitools::NewTestError.new new_test_error_message(r), r if r.new?
|
98
|
+
raise Applitools::DiffsFoundError.new diffs_found_error_message(r), r if r.unresolved? && !r.new?
|
99
|
+
raise Applitools::TestFailedError.new test_failed_error_message(r), r if r.failed?
|
100
|
+
end
|
101
|
+
end
|
102
|
+
test_list.map(&:test_result).first
|
103
|
+
end
|
104
|
+
|
105
|
+
def open?
|
106
|
+
opened
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_all_test_results
|
110
|
+
test_list.map(&:test_result)
|
111
|
+
end
|
112
|
+
|
113
|
+
def new_test_error_message(result)
|
114
|
+
original_results = result.original_results
|
115
|
+
"New test '#{original_results['name']}' " \
|
116
|
+
"of '#{original_results['appName']}' " \
|
117
|
+
"Please approve the baseline at #{original_results['appUrls']['session']} "
|
118
|
+
end
|
119
|
+
|
120
|
+
def diffs_found_error_message(result)
|
121
|
+
original_results = result.original_results
|
122
|
+
"Test '#{original_results['name']}' " \
|
123
|
+
"of '#{original_results['appname']}' " \
|
124
|
+
"detected differences! See details at #{original_results['appUrls']['session']}"
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_failed_error_message(result)
|
128
|
+
original_results = result.original_results
|
129
|
+
"Test '#{original_results['name']}' of '#{original_results['appName']}' " \
|
130
|
+
"is failed! See details at #{original_results['appUrls']['session']}"
|
131
|
+
end
|
132
|
+
private :new_test_error_message, :diffs_found_error_message, :test_failed_error_message
|
133
|
+
|
134
|
+
# Takes a snapshot of the application under test and matches it with the expected output.
|
135
|
+
#
|
136
|
+
# @param [String] tag An optional tag to be assosiated with the snapshot.
|
137
|
+
# @param [Fixnum] match_timeout The amount of time to retry matching (seconds)
|
138
|
+
def check_window(tag = nil, match_timeout = USE_DEFAULT_MATCH_TIMEOUT)
|
139
|
+
target = Applitools::Selenium::Target.window.tap do |t|
|
140
|
+
t.timeout(match_timeout)
|
141
|
+
t.fully if force_full_page_screenshot
|
142
|
+
end
|
143
|
+
check(tag, target)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Takes a snapshot of the application under test and matches a region of
|
147
|
+
# a specific element with the expected region output.
|
148
|
+
#
|
149
|
+
# @param [Applitools::Selenium::Element] element Represents a region to check.
|
150
|
+
# @param [Symbol] how a finder, such :css or :id. Selects a finder will be used to find an element
|
151
|
+
# See Selenium::Webdriver::Element#find_element documentation for full list of possible finders.
|
152
|
+
# @param [String] what The value will be passed to a specified finder. If finder is :css it must be a css selector.
|
153
|
+
# @param [Hash] options
|
154
|
+
# @option options [String] :tag An optional tag to be associated with the snapshot.
|
155
|
+
# @option options [Fixnum] :match_timeout The amount of time to retry matching. (Seconds)
|
156
|
+
# @option options [Boolean] :stitch_content If set to true, will try to get full content of the element
|
157
|
+
# (including hidden content due overflow settings) by scrolling the element,
|
158
|
+
# taking and stitching partial screenshots.
|
159
|
+
# @example Check region by element
|
160
|
+
# check_region(element, tag: 'Check a region by element', match_timeout: 3, stitch_content: false)
|
161
|
+
# @example Check region by css selector
|
162
|
+
# check_region(:css, '.form-row .input#e_mail', tag: 'Check a region by element', match_timeout: 3,
|
163
|
+
# stitch_content: false)
|
164
|
+
# @!parse def check_region(element, how=nil, what=nil, options = {}); end
|
165
|
+
def check_region(*args)
|
166
|
+
options = { timeout: USE_DEFAULT_MATCH_TIMEOUT, tag: nil }.merge! Applitools::Utils.extract_options!(args)
|
167
|
+
target = Applitools::Selenium::Target.new.region(*args).timeout(options[:match_timeout])
|
168
|
+
target.fully if options[:stitch_content]
|
169
|
+
check(options[:tag], target)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Validates the contents of an iframe and matches it with the expected output.
|
173
|
+
#
|
174
|
+
# @param [Hash] options The specific parameters of the desired screenshot.
|
175
|
+
# @option options [Fixnum] :timeout The amount of time to retry matching. (Seconds)
|
176
|
+
# @option options [String] :tag An optional tag to be associated with the snapshot.
|
177
|
+
# @option options [String] :frame Frame element or frame name or frame id.
|
178
|
+
# @option options [String] :name_or_id The name or id of the target frame (deprecated. use :frame instead).
|
179
|
+
# @option options [String] :frame_element The frame element (deprecated. use :frame instead).
|
180
|
+
# @return [Applitools::MatchResult] The match results.
|
181
|
+
|
182
|
+
def check_frame(options = {})
|
183
|
+
options = { timeout: USE_DEFAULT_MATCH_TIMEOUT, tag: nil }.merge!(options)
|
184
|
+
frame = options[:frame] || options[:frame_element] || options[:name_or_id]
|
185
|
+
target = Applitools::Selenium::Target.frame(frame).timeout(options[:timeout]).fully
|
186
|
+
check(options[:tag], target)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Validates the contents of a region in an iframe and matches it with the expected output.
|
190
|
+
#
|
191
|
+
# @param [Hash] options The specific parameters of the desired screenshot.
|
192
|
+
# @option options [String] :name_or_id The name or id of the target frame (deprecated. use :frame instead).
|
193
|
+
# @option options [String] :frame_element The frame element (deprecated. use :frame instead).
|
194
|
+
# @option options [String] :frame Frame element or frame name or frame id.
|
195
|
+
# @option options [String] :tag An optional tag to be associated with the snapshot.
|
196
|
+
# @option options [Symbol] :by By which identifier to find the region (e.g :css, :id).
|
197
|
+
# @option options [Fixnum] :timeout The amount of time to retry matching. (Seconds)
|
198
|
+
# @option options [Boolean] :stitch_content Whether to stitch the content or not.
|
199
|
+
# @return [Applitools::MatchResult] The match results.
|
200
|
+
def check_region_in_frame(options = {})
|
201
|
+
options = { timeout: USE_DEFAULT_MATCH_TIMEOUT, tag: nil, stitch_content: false }.merge!(options)
|
202
|
+
Applitools::ArgumentGuard.not_nil options[:by], 'options[:by]'
|
203
|
+
Applitools::ArgumentGuard.is_a? options[:by], 'options[:by]', Array
|
204
|
+
|
205
|
+
how_what = options.delete(:by)
|
206
|
+
frame = options[:frame] || options[:frame_element] || options[:name_or_id]
|
207
|
+
|
208
|
+
target = Applitools::Selenium::Target.new.timeout(options[:timeout])
|
209
|
+
target.frame(frame) if frame
|
210
|
+
target.fully if options[:stitch_content]
|
211
|
+
target.region(*how_what)
|
212
|
+
|
213
|
+
check(options[:tag], target)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Use this method to perform seamless testing with selenium through eyes driver.
|
217
|
+
# It yields a block and passes to it an Applitools::Selenium::Driver instance, which wraps standard driver.
|
218
|
+
# Using Selenium methods inside the 'test' block will send the messages to Selenium
|
219
|
+
# after creating the Eyes triggers for them. Options are similar to {open}
|
220
|
+
# @yieldparam driver [Applitools::Selenium::Driver] Gives a driver to a block, which translates calls to a native
|
221
|
+
# Selemium::Driver instance
|
222
|
+
# @example
|
223
|
+
# eyes.test(app_name: 'my app', test_name: 'my test') do |driver|
|
224
|
+
# driver.get "http://www.google.com"
|
225
|
+
# driver.check_window("initial")
|
226
|
+
# end
|
227
|
+
def test(options = {}, &_block)
|
228
|
+
open(options)
|
229
|
+
yield(driver)
|
230
|
+
close
|
231
|
+
ensure
|
232
|
+
abort_if_not_closed
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|