eyes_selenium 1.25.0 → 1.26.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/eyes_selenium/eyes/agent_connector.rb +1 -1
- data/lib/eyes_selenium/eyes/driver.rb +1 -1
- data/lib/eyes_selenium/eyes/eyes.rb +32 -18
- data/lib/eyes_selenium/eyes/match_window_task.rb +59 -33
- data/lib/eyes_selenium/eyes/mouse_trigger.rb +2 -2
- data/lib/eyes_selenium/eyes/region.rb +5 -0
- data/lib/eyes_selenium/version.rb +1 -1
- data/test_script.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODUwYjE0ZmI1ODE3ZjNiZTFlODMwOGNlNGRjODJlMmUyOTBmMzQzZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NmI0YjkyYWRhMmQ5NTMxY2NkZWNhZDc1YTc0ZDJiNjBlMDk5NWM1NA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OThkYjg4YTZkZDhhMTRhODE2MTk2Y2VlOGM2Zjk3NTk3NDYxOTA1N2MwODZj
|
10
|
+
OWZkN2QwMDIwMzcyYmU5MGQ1YjgwMThjMzg5ZGU4ZDI1MGE2ZGVhY2QxYTFk
|
11
|
+
YjEzMmQ2NDcyZWUzNjIzMzI2ODUxOTNmZjAxOTA4MTg1ZDkwNTk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YzcwZDA5MzZhOTRkYWUxYmRmNmQ5ZDdjMThiNTU0YmM3ODVkYWQxMGZmZGUz
|
14
|
+
MmVmZTczODhmOTExZTU1YzEyOTQ5NDliOTg4ZWUzZDBkZTM3YzM5YThiNWVk
|
15
|
+
YmFlY2M4OWNjOWQ1ZDY3NzM5MTgxZTA0MTg1MDkwY2Y5ZWUwMzA=
|
@@ -15,7 +15,7 @@ class Applitools::AgentConnector
|
|
15
15
|
|
16
16
|
def match_window(session, data)
|
17
17
|
self.class.headers 'Content-Type' => 'application/octet-stream'
|
18
|
-
json_data = data.to_hash.to_json.encode('
|
18
|
+
json_data = data.to_hash.to_json.encode('BINARY') # Notice that this does not include the screenshot
|
19
19
|
body = [json_data.length].pack('L>') + json_data + data.screenshot
|
20
20
|
|
21
21
|
res = self.class.post(uri + "/#{session.id}",basic_auth: auth, body: body)
|
@@ -74,7 +74,7 @@ class Applitools::Driver
|
|
74
74
|
def user_agent
|
75
75
|
execute_script 'return navigator.userAgent'
|
76
76
|
rescue => e
|
77
|
-
|
77
|
+
EyesLogger.info "getUserAgent(): Failed to obtain user-agent string (#{e.message})"
|
78
78
|
end
|
79
79
|
|
80
80
|
private
|
@@ -100,25 +100,16 @@ class Applitools::Eyes
|
|
100
100
|
user_inputs.clear
|
101
101
|
end
|
102
102
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
103
|
+
def check_region(how, what, tag=nil)
|
104
|
+
element_to_check = driver.find_element(how, what)
|
105
|
+
location = element_to_check.location
|
106
|
+
size = element_to_check.size
|
107
|
+
region = Applitools::Region.new(location.x, location.y, size.width, size.height)
|
108
|
+
check_region_(region, tag)
|
109
|
+
end
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
self.should_match_window_run_once_on_timeout = true
|
114
|
-
unless session.new_session?
|
115
|
-
EyesLogger.info %( "mismatch #{ tag ? '' : "(#{tag})" } )
|
116
|
-
if failure_reports.to_i == Applitools::FailureReports::IMMEDIATE
|
117
|
-
raise Applitools::TestFailedError.new("Mismatch found in '#{session_start_info.scenario_id_or_name}'"\
|
118
|
-
" of '#{session_start_info.app_id_or_name}'")
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
111
|
+
def check_window(tag=nil)
|
112
|
+
check_region_(Applitools::Region::EMPTY, tag)
|
122
113
|
end
|
123
114
|
|
124
115
|
def close
|
@@ -238,4 +229,27 @@ class Applitools::Eyes
|
|
238
229
|
@viewport_size = Applitools::ViewportSize.new(driver).extract_viewport_from_browser!
|
239
230
|
end
|
240
231
|
end
|
232
|
+
|
233
|
+
def check_region_(region, tag=nil)
|
234
|
+
return if disabled?
|
235
|
+
raise Applitools::EyesError.new('region cannot be nil!') if region.nil?
|
236
|
+
raise Applitools::EyesError.new('Eyes not open') if !open?
|
237
|
+
|
238
|
+
unless session
|
239
|
+
start_session
|
240
|
+
self.match_window_task = Applitools::MatchWindowTask.new(self, agent_connector, session, driver, match_timeout)
|
241
|
+
end
|
242
|
+
|
243
|
+
as_expected = match_window_task.match_window(region, tag, should_match_window_run_once_on_timeout)
|
244
|
+
unless as_expected
|
245
|
+
self.should_match_window_run_once_on_timeout = true
|
246
|
+
unless session.new_session?
|
247
|
+
EyesLogger.info %( "mismatch #{ tag ? '' : "(#{tag})" } )
|
248
|
+
if failure_reports.to_i == Applitools::FailureReports::IMMEDIATE
|
249
|
+
raise Applitools::TestFailedError.new("Mismatch found in '#{session_start_info.scenario_id_or_name}'"\
|
250
|
+
" of '#{session_start_info.app_id_or_name}'")
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
241
255
|
end
|
@@ -7,7 +7,7 @@ class Applitools::MatchWindowTask
|
|
7
7
|
MATCH_INTERVAL = 0.5
|
8
8
|
AppOutput = Struct.new(:title, :screenshot64)
|
9
9
|
|
10
|
-
attr_reader :eyes, :agent_connector, :session, :driver, :max_window_load_time
|
10
|
+
attr_reader :eyes, :agent_connector, :session, :driver, :max_window_load_time, :last_checked_window ,:last_screenshot_bounds
|
11
11
|
|
12
12
|
public
|
13
13
|
## max_load_time: maximum wait time for check window, in seconds
|
@@ -18,65 +18,94 @@ class Applitools::MatchWindowTask
|
|
18
18
|
@driver = driver
|
19
19
|
@max_window_load_time = max_window_load_time
|
20
20
|
@last_checked_window = nil # +ChunkyPNG::Canvas+
|
21
|
+
@last_screenshot_bounds = Applitools::Region::EMPTY # +Applitools::Region+
|
21
22
|
@current_screenshot = nil # +ChunkyPNG::Canvas+
|
22
23
|
end
|
23
24
|
|
24
|
-
def match_window(tag,run_once_after_wait=false)
|
25
|
+
def match_window(region, tag,run_once_after_wait=false)
|
25
26
|
res = if max_window_load_time.zero?
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
run(region, tag)
|
28
|
+
elsif run_once_after_wait
|
29
|
+
run(region, tag, max_window_load_time)
|
30
|
+
else
|
31
|
+
run_with_intervals(region, tag, max_window_load_time)
|
32
|
+
end
|
33
|
+
@last_checked_window = @current_screenshot
|
34
|
+
@last_screenshot_bounds = region.empty? ? Applitools::Region.new(0, 0, last_checked_window.width, last_checked_window.height) : region
|
32
35
|
#noinspection RubyUnnecessaryReturnStatement
|
33
36
|
driver.eyes.clear_user_inputs and return res
|
34
37
|
end
|
35
38
|
|
36
|
-
def run(tag, wait_before_run=nil)
|
39
|
+
def run(region, tag, wait_before_run=nil)
|
37
40
|
sleep(wait_before_run) if wait_before_run
|
38
|
-
match(tag)
|
41
|
+
match(region, tag)
|
39
42
|
end
|
40
43
|
|
41
|
-
def run_with_intervals(tag, total_run_time)
|
44
|
+
def run_with_intervals(region, tag, total_run_time)
|
42
45
|
start = Time.now
|
43
46
|
match_retry = total_run_time
|
44
47
|
while match_retry > 0
|
45
48
|
sleep(MATCH_INTERVAL)
|
46
|
-
return true if match(tag, true)
|
49
|
+
return true if match(region, tag, true)
|
47
50
|
match_retry -= (Time.now - start)
|
48
51
|
end
|
49
52
|
## lets try one more time if we still don't have a match
|
50
|
-
match(tag)
|
53
|
+
match(region, tag)
|
51
54
|
end
|
52
55
|
|
53
56
|
private
|
54
57
|
|
55
|
-
def prep_match_data(tag, ignore_mismatch)
|
58
|
+
def prep_match_data(region, tag, ignore_mismatch)
|
56
59
|
title = eyes.title
|
60
|
+
# 'encoded', as in 'png'.
|
57
61
|
current_screenshot_encoded = Base64.decode64(driver.screenshot_as(:base64))
|
58
62
|
@current_screenshot = ChunkyPNG::Image.from_blob(current_screenshot_encoded)
|
63
|
+
# If a region was defined, we refer to the sub-image defined by the region.
|
64
|
+
unless region.empty?
|
65
|
+
@current_screenshot.crop!(region.left, region.top, region.width, region.height)
|
66
|
+
current_screenshot_encoded = @current_screenshot.to_blob.force_encoding('BINARY')
|
67
|
+
end
|
59
68
|
compressed_screenshot = Applitools::Utils::ImageDeltaCompressor.compress_by_raw_blocks(@current_screenshot,
|
60
69
|
current_screenshot_encoded,
|
61
|
-
|
70
|
+
last_checked_window)
|
62
71
|
app_output = AppOutput.new(title, nil)
|
63
72
|
user_inputs = []
|
64
|
-
if
|
65
|
-
user_inputs = driver.eyes.user_inputs
|
66
|
-
else
|
73
|
+
if !last_checked_window.nil?
|
67
74
|
driver.eyes.user_inputs.each do |trigger|
|
68
|
-
if trigger.is_a?
|
75
|
+
if trigger.is_a?(Applitools::MouseTrigger)
|
76
|
+
updated_trigger = nil
|
69
77
|
trigger_left = trigger.control.left + trigger.location.x
|
70
78
|
trigger_top = trigger.control.top + trigger.location.y
|
71
|
-
if trigger_left
|
72
|
-
|
79
|
+
if last_screenshot_bounds.contains?(trigger_left, trigger_top)
|
80
|
+
trigger.control.intersect(last_screenshot_bounds)
|
81
|
+
if trigger.control.empty?
|
82
|
+
trigger_left = trigger_left - last_screenshot_bounds.left
|
83
|
+
trigger_top = trigger_top -last_screenshot_bounds.top
|
84
|
+
updated_trigger = Applitools::MouseTrigger.new(trigger.mouse_action, trigger.control, Selenium::WebDriver::Point.new(trigger_left, trigger_top))
|
85
|
+
else
|
86
|
+
trigger_left = trigger_left - trigger.control.left
|
87
|
+
trigger_top = trigger_top - trigger.control.top
|
88
|
+
control_left = trigger.control.left - last_screenshot_bounds.left
|
89
|
+
control_top = trigger.control.top - last_screenshot_bounds.top
|
90
|
+
updated_control = Applitools::Region.new(control_left, control_top, trigger.control.width, trigger.control.height)
|
91
|
+
updated_trigger = Applitools::MouseTrigger.new(trigger.mouse_action, updated_control, Selenium::WebDriver::Point.new(trigger_left, trigger_top))
|
92
|
+
end
|
93
|
+
user_inputs << updated_trigger
|
73
94
|
else
|
74
95
|
EyesLogger.info "Trigger ignored: #{trigger} (out of bounds)"
|
75
96
|
end
|
76
|
-
elsif trigger.is_a?
|
77
|
-
|
78
|
-
|
79
|
-
|
97
|
+
elsif trigger.is_a?(Applitools::TextTrigger)
|
98
|
+
unless trigger.control.empty?
|
99
|
+
trigger.control.intersect(last_screenshot_bounds)
|
100
|
+
unless trigger.control.empty?
|
101
|
+
control_left = trigger.control.left - last_screenshot_bounds.left
|
102
|
+
control_top = trigger.control.top - last_screenshot_bounds.top
|
103
|
+
updated_control = Applitools::Region.new(control_left, control_top, trigger.control.width, trigger.control.height)
|
104
|
+
updated_trigger = Applitools::TextTrigger.new(trigger.text, updated_control)
|
105
|
+
user_inputs << updated_trigger
|
106
|
+
else
|
107
|
+
EyesLogger.info "Trigger ignored: #{trigger} (control out of bounds)"
|
108
|
+
end
|
80
109
|
else
|
81
110
|
EyesLogger.info "Trigger ignored: #{trigger} (out of bounds)"
|
82
111
|
end
|
@@ -84,17 +113,14 @@ class Applitools::MatchWindowTask
|
|
84
113
|
EyesLogger.info "Trigger ignored: #{trigger} (Unrecognized trigger)"
|
85
114
|
end
|
86
115
|
end
|
116
|
+
else
|
117
|
+
EyesLogger.info 'Triggers ignored: no previous window checked'
|
87
118
|
end
|
88
119
|
Applitools::MatchWindowData.new(app_output, user_inputs, tag, ignore_mismatch, compressed_screenshot)
|
89
120
|
end
|
90
121
|
|
91
|
-
def match(tag, ignore_mismatch=false)
|
92
|
-
data = prep_match_data(tag, ignore_mismatch)
|
93
|
-
|
94
|
-
# If the server stored this image, it will be used as a base for our next screenshot compression
|
95
|
-
unless ignore_mismatch
|
96
|
-
@last_checked_window = @current_screenshot
|
97
|
-
end
|
98
|
-
as_expected
|
122
|
+
def match(region, tag, ignore_mismatch=false)
|
123
|
+
data = prep_match_data(region, tag, ignore_mismatch)
|
124
|
+
agent_connector.match_window(session, data)
|
99
125
|
end
|
100
126
|
end
|
@@ -5,14 +5,14 @@ class Applitools::MouseTrigger
|
|
5
5
|
attr_reader :mouse_action, :control, :location
|
6
6
|
|
7
7
|
def initialize(mouse_action, control, location)
|
8
|
-
@mouse_action =
|
8
|
+
@mouse_action = mouse_action
|
9
9
|
@control = control
|
10
10
|
@location = location
|
11
11
|
end
|
12
12
|
|
13
13
|
def to_hash
|
14
14
|
{
|
15
|
-
"$type" => "Applitools.Models.MouseTrigger, Core", mouseAction: mouse_action,
|
15
|
+
"$type" => "Applitools.Models.MouseTrigger, Core", mouseAction: MOUSE_ACTION[mouse_action],
|
16
16
|
control: control.to_hash, location: Hash[location.each_pair.to_a]
|
17
17
|
}
|
18
18
|
end
|
@@ -49,6 +49,11 @@ class Applitools::Region
|
|
49
49
|
self.height = i_bottom - i_top
|
50
50
|
end
|
51
51
|
|
52
|
+
def contains?(other_left, other_top)
|
53
|
+
other_left >= left && other_left <= right && \
|
54
|
+
other_top >= top && other_top <= bottom
|
55
|
+
end
|
56
|
+
|
52
57
|
def middle_offset
|
53
58
|
mid_x = width / 2
|
54
59
|
mid_y = height / 2
|
data/test_script.rb
CHANGED
@@ -14,6 +14,7 @@ begin
|
|
14
14
|
eyes.test(app_name: 'Ruby SDK', test_name: 'Applitools website test', viewport_size: {width: 1024, height: 768}, driver: my_webdriver) do |driver|
|
15
15
|
driver.get "http://www.applitools.com"
|
16
16
|
eyes.check_window("initial")
|
17
|
+
eyes.check_region(:css, 'li.pricing', 'Pricing button')
|
17
18
|
driver.find_element(:css, "li.pricing a").click
|
18
19
|
eyes.check_window("pricing page")
|
19
20
|
el = driver.find_elements(:css, ".footer-row a").first
|
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: 1.
|
4
|
+
version: 1.26.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Applitools team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: selenium-webdriver
|