rwebspec 1.4.0 → 1.4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +300 -300
- data/MIT-LICENSE +21 -21
- data/README +32 -32
- data/Rakefile +94 -94
- data/lib/rspec_extensions.rb +50 -50
- data/lib/rwebspec/assert.rb +361 -361
- data/lib/rwebspec/clickJSDialog.rb +15 -15
- data/lib/rwebspec/context.rb +24 -24
- data/lib/rwebspec/driver.rb +734 -734
- data/lib/rwebspec/itest_plugin.rb +68 -68
- data/lib/rwebspec/matchers/contains_text.rb +37 -37
- data/lib/rwebspec/popup.rb +147 -147
- data/lib/rwebspec/rspec_helper.rb +96 -96
- data/lib/rwebspec/test_script.rb +8 -8
- data/lib/rwebspec/test_utils.rb +171 -171
- data/lib/rwebspec/using_pages.rb +49 -49
- data/lib/rwebspec/web_browser.rb +528 -528
- data/lib/rwebspec/web_page.rb +94 -94
- data/lib/rwebspec/web_testcase.rb +36 -36
- data/lib/rwebspec.rb +31 -31
- data/lib/rwebunit.rb +3 -3
- data/lib/watir_extensions.rb +69 -69
- metadata +6 -6
@@ -1,68 +1,68 @@
|
|
1
|
-
require 'socket'
|
2
|
-
|
3
|
-
module RWebSpec
|
4
|
-
module ITestPlugin
|
5
|
-
|
6
|
-
def connect_to_itest(message_type, body)
|
7
|
-
begin
|
8
|
-
the_message = message_type + "|" + body
|
9
|
-
if @last_message == the_message then # ignore the message same as preivous one
|
10
|
-
return
|
11
|
-
end
|
12
|
-
itest_port = $ITEST2_TRACE_PORT || 7025
|
13
|
-
itest_socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
|
14
|
-
itest_socket.connect(Socket.pack_sockaddr_in(itest_port, '127.0.0.1'))
|
15
|
-
itest_socket.puts(the_message)
|
16
|
-
@last_message = the_message
|
17
|
-
itest_socket.close
|
18
|
-
rescue => e
|
19
|
-
end
|
20
|
-
end
|
21
|
-
alias connect_to_itest2 connect_to_itest
|
22
|
-
|
23
|
-
def debug(message)
|
24
|
-
connect_to_itest(" DEBUG", message + "\r\n") if $RUN_IN_ITEST
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
# Support of iTest to ajust the intervals between keystroke/mouse operations
|
29
|
-
def operation_delay
|
30
|
-
begin
|
31
|
-
if $ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY > 0 &&
|
32
|
-
$ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY < 30000 then # max 30 seconds
|
33
|
-
sleep($ITEST2_OPERATION_DELAY / 1000)
|
34
|
-
end
|
35
|
-
|
36
|
-
while $ITEST2_PAUSE
|
37
|
-
debug("Paused, waiting ...")
|
38
|
-
sleep 1
|
39
|
-
end
|
40
|
-
rescue => e
|
41
|
-
puts "Error on delaying: #{e}"
|
42
|
-
# ignore
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# find out the line (and file) the execution is on, and notify iTest via Socket
|
47
|
-
def dump_caller_stack
|
48
|
-
return unless $ITEST2_TRACE_EXECUTION
|
49
|
-
begin
|
50
|
-
caller.each_with_index do |position, idx|
|
51
|
-
next unless position =~ /\A(.*?):(\d+)/
|
52
|
-
file = $1
|
53
|
-
# TODO: send multiple trace to be parse with pages.rb
|
54
|
-
# next if file =~ /example\/example_methods\.rb$/ or file =~ /example\/example_group_methods\.rb$/ or file =~ /driver\.rb$/ or file =~ /timeout\.rb$/ # don't include rspec or ruby trace
|
55
|
-
|
56
|
-
if file.include?("_spec.rb") || file.include?("_test.rb") || file.include?("_cmd.rb")
|
57
|
-
connect_to_itest(" TRACE", position)
|
58
|
-
end
|
59
|
-
|
60
|
-
break if idx > 4 or file =~ /"_spec\.rb$/
|
61
|
-
end
|
62
|
-
rescue => e
|
63
|
-
puts "failed to capture log: #{e}"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
end
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module RWebSpec
|
4
|
+
module ITestPlugin
|
5
|
+
|
6
|
+
def connect_to_itest(message_type, body)
|
7
|
+
begin
|
8
|
+
the_message = message_type + "|" + body
|
9
|
+
if @last_message == the_message then # ignore the message same as preivous one
|
10
|
+
return
|
11
|
+
end
|
12
|
+
itest_port = $ITEST2_TRACE_PORT || 7025
|
13
|
+
itest_socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
|
14
|
+
itest_socket.connect(Socket.pack_sockaddr_in(itest_port, '127.0.0.1'))
|
15
|
+
itest_socket.puts(the_message)
|
16
|
+
@last_message = the_message
|
17
|
+
itest_socket.close
|
18
|
+
rescue => e
|
19
|
+
end
|
20
|
+
end
|
21
|
+
alias connect_to_itest2 connect_to_itest
|
22
|
+
|
23
|
+
def debug(message)
|
24
|
+
connect_to_itest(" DEBUG", message + "\r\n") if $RUN_IN_ITEST
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Support of iTest to ajust the intervals between keystroke/mouse operations
|
29
|
+
def operation_delay
|
30
|
+
begin
|
31
|
+
if $ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY > 0 &&
|
32
|
+
$ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY < 30000 then # max 30 seconds
|
33
|
+
sleep($ITEST2_OPERATION_DELAY / 1000)
|
34
|
+
end
|
35
|
+
|
36
|
+
while $ITEST2_PAUSE
|
37
|
+
debug("Paused, waiting ...")
|
38
|
+
sleep 1
|
39
|
+
end
|
40
|
+
rescue => e
|
41
|
+
puts "Error on delaying: #{e}"
|
42
|
+
# ignore
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# find out the line (and file) the execution is on, and notify iTest via Socket
|
47
|
+
def dump_caller_stack
|
48
|
+
return unless $ITEST2_TRACE_EXECUTION
|
49
|
+
begin
|
50
|
+
caller.each_with_index do |position, idx|
|
51
|
+
next unless position =~ /\A(.*?):(\d+)/
|
52
|
+
file = $1
|
53
|
+
# TODO: send multiple trace to be parse with pages.rb
|
54
|
+
# next if file =~ /example\/example_methods\.rb$/ or file =~ /example\/example_group_methods\.rb$/ or file =~ /driver\.rb$/ or file =~ /timeout\.rb$/ # don't include rspec or ruby trace
|
55
|
+
|
56
|
+
if file.include?("_spec.rb") || file.include?("_test.rb") || file.include?("_cmd.rb")
|
57
|
+
connect_to_itest(" TRACE", position)
|
58
|
+
end
|
59
|
+
|
60
|
+
break if idx > 4 or file =~ /"_spec\.rb$/
|
61
|
+
end
|
62
|
+
rescue => e
|
63
|
+
puts "failed to capture log: #{e}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -1,37 +1,37 @@
|
|
1
|
-
class ContainsText
|
2
|
-
|
3
|
-
# this is what the matcher is called on.
|
4
|
-
# In this case:
|
5
|
-
# foo.should contains(:bars)
|
6
|
-
# foo would be passed to the +initialize+
|
7
|
-
def initialize(expected)
|
8
|
-
@expected = expected
|
9
|
-
end
|
10
|
-
|
11
|
-
def matches?(actual)
|
12
|
-
@actual = actual
|
13
|
-
return actual && actual.include?(@expected)
|
14
|
-
end
|
15
|
-
|
16
|
-
def actual_text
|
17
|
-
@actual.to_s.length > 1000000 ? @actual[0, 1000] : @actual
|
18
|
-
end
|
19
|
-
|
20
|
-
# error message for should
|
21
|
-
def failure_message
|
22
|
-
"expected #{actual_text} not to contains #{@expected}, but it did't"
|
23
|
-
end
|
24
|
-
|
25
|
-
# error message for should_not
|
26
|
-
def negative_failure_message
|
27
|
-
"expected #{actual_text} not to contains #{@expected}, but it did"
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
# This method is the one you use with should/should_not
|
34
|
-
def contains_text?(expected)
|
35
|
-
ContainsText.new(expected)
|
36
|
-
end
|
37
|
-
alias contains? contains_text?
|
1
|
+
class ContainsText
|
2
|
+
|
3
|
+
# this is what the matcher is called on.
|
4
|
+
# In this case:
|
5
|
+
# foo.should contains(:bars)
|
6
|
+
# foo would be passed to the +initialize+
|
7
|
+
def initialize(expected)
|
8
|
+
@expected = expected
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches?(actual)
|
12
|
+
@actual = actual
|
13
|
+
return actual && actual.include?(@expected)
|
14
|
+
end
|
15
|
+
|
16
|
+
def actual_text
|
17
|
+
@actual.to_s.length > 1000000 ? @actual[0, 1000] : @actual
|
18
|
+
end
|
19
|
+
|
20
|
+
# error message for should
|
21
|
+
def failure_message
|
22
|
+
"expected #{actual_text} not to contains #{@expected}, but it did't"
|
23
|
+
end
|
24
|
+
|
25
|
+
# error message for should_not
|
26
|
+
def negative_failure_message
|
27
|
+
"expected #{actual_text} not to contains #{@expected}, but it did"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# This method is the one you use with should/should_not
|
34
|
+
def contains_text?(expected)
|
35
|
+
ContainsText.new(expected)
|
36
|
+
end
|
37
|
+
alias contains? contains_text?
|
data/lib/rwebspec/popup.rb
CHANGED
@@ -1,147 +1,147 @@
|
|
1
|
-
module RWebSpec
|
2
|
-
module Popup
|
3
|
-
|
4
|
-
#= Popup
|
5
|
-
#
|
6
|
-
|
7
|
-
# Start background thread to click popup windows
|
8
|
-
# Warning:
|
9
|
-
# Make browser window active
|
10
|
-
# Don't mouse your mouse to focus other window during test execution
|
11
|
-
def check_for_popups
|
12
|
-
autoit = WIN32OLE.new('AutoItX3.Control')
|
13
|
-
#
|
14
|
-
# Do forever - assumes popups could occur anywhere/anytime in your
|
15
|
-
# application.
|
16
|
-
loop do
|
17
|
-
# Look for window with given title. Give up after 1 second.
|
18
|
-
ret = autoit.WinWait('Windows Internet Explorer', '', 1)
|
19
|
-
#
|
20
|
-
# If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).
|
21
|
-
if (ret==1) then
|
22
|
-
autoit.Send('{enter}')
|
23
|
-
end
|
24
|
-
#
|
25
|
-
# Take a rest to avoid chewing up cycles and give another thread a go.
|
26
|
-
# Then resume the loop.
|
27
|
-
sleep(3)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
##
|
32
|
-
# Check for "Security Information" and "Security Alert" alert popup, click 'Yes'
|
33
|
-
#
|
34
|
-
# Usage: For individual test suite
|
35
|
-
#
|
36
|
-
# before(:all) do
|
37
|
-
# $popup = Thread.new { check_for_alerts }
|
38
|
-
# open_in_browser
|
39
|
-
# ...
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# after(:all) do
|
43
|
-
# close_browser
|
44
|
-
# Thread.kill($popup)
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
# or for all tests,
|
48
|
-
# $popup = Thread.new { check_for_alerts }
|
49
|
-
# at_exit{ Thread.kill($popup) }
|
50
|
-
def check_for_security_alerts
|
51
|
-
autoit = WIN32OLE.new('AutoItX3.Control')
|
52
|
-
loop do
|
53
|
-
["Security Alert", "Security Information"].each do |win_title|
|
54
|
-
ret = autoit.WinWait(win_title, '', 1)
|
55
|
-
if (ret==1) then
|
56
|
-
autoit.Send('{Y}')
|
57
|
-
end
|
58
|
-
end
|
59
|
-
sleep(3)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def verify_alert(title = "Microsoft Internet Explorer", button = "OK")
|
64
|
-
if is_windows? && !is_firefox?
|
65
|
-
WIN32OLE.new('AutoItX3.Control').ControlClick(title, '', button)
|
66
|
-
else
|
67
|
-
raise "This function only supports IE"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def click_button_in_security_information_popup(button = "&Yes")
|
72
|
-
verify_alert("Security Information", "", button)
|
73
|
-
end
|
74
|
-
alias click_security_information_popup click_button_in_security_information_popup
|
75
|
-
|
76
|
-
def click_button_in_security_alert_popup(button = "&Yes")
|
77
|
-
verify_alert("Security Alert", "", button)
|
78
|
-
end
|
79
|
-
alias click_security_alert_popup click_button_in_security_alert_popup
|
80
|
-
|
81
|
-
def click_button_in_javascript_popup(button = "OK")
|
82
|
-
verify_alert()
|
83
|
-
end
|
84
|
-
alias click_javascript_popup click_button_in_javascript_popup
|
85
|
-
|
86
|
-
##
|
87
|
-
# This only works for IEs
|
88
|
-
# Cons:
|
89
|
-
# - Slow
|
90
|
-
# - only works in IE
|
91
|
-
# - does not work for security alert ?
|
92
|
-
def ie_popup_clicker(button_name = "OK", max_wait = 15)
|
93
|
-
require 'watir/contrib/enabled_popup'
|
94
|
-
require 'win32ole'
|
95
|
-
hwnd = ie.enabled_popup(15)
|
96
|
-
if (hwnd) #yeah! a popup
|
97
|
-
popup = WinClicker.new
|
98
|
-
popup.makeWindowActive(hwnd) #Activate the window.
|
99
|
-
popup.clickWindowsButton_hwnd(hwnd, button_name) #Click the button
|
100
|
-
#popup.clickWindowsButton(/Internet/,button_name,30)
|
101
|
-
popup = nil
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def click_popup_window(button, wait_time= 9, user_input=nil )
|
106
|
-
@web_browser.start_clicker(button, wait_time, user_input)
|
107
|
-
sleep 0.5
|
108
|
-
end
|
109
|
-
# run a separate process waiting for the popup window to click
|
110
|
-
#
|
111
|
-
#
|
112
|
-
def prepare_to_click_button_in_popup(button = "OK", wait_time = 3)
|
113
|
-
# !@web_browser.is_firefox?
|
114
|
-
# TODO: firefox is OK
|
115
|
-
if RUBY_PLATFORM =~ /mswin/ then
|
116
|
-
start_checking_js_dialog(button, wait_time)
|
117
|
-
else
|
118
|
-
raise "this only support on Windows and on IE"
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# Start a background process to click the button on a javascript popup window
|
123
|
-
def start_checking_js_dialog(button = "OK", wait_time = 3)
|
124
|
-
w = WinClicker.new
|
125
|
-
longName = File.expand_path(File.dirname(__FILE__)).gsub("/", "\\" )
|
126
|
-
shortName = w.getShortFileName(longName)
|
127
|
-
c = "start ruby #{shortName}\\clickJSDialog.rb #{button} #{wait_time} "
|
128
|
-
w.winsystem(c)
|
129
|
-
w = nil
|
130
|
-
end
|
131
|
-
|
132
|
-
# Click the button in javascript popup dialog
|
133
|
-
# Usage:
|
134
|
-
# click_button_in_popup_after { click_link('Cancel')}
|
135
|
-
# click_button_in_popup_after("OK") { click_link('Cancel')}
|
136
|
-
#
|
137
|
-
def click_button_in_popup_after(options = {:button => "OK", :wait_time => 3}, &block)
|
138
|
-
if is_windows? then
|
139
|
-
start_checking_js_dialog(options[:button], options[:wait_time])
|
140
|
-
yield
|
141
|
-
else
|
142
|
-
raise "this only support on Windows and on IE"
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|
147
|
-
end
|
1
|
+
module RWebSpec
|
2
|
+
module Popup
|
3
|
+
|
4
|
+
#= Popup
|
5
|
+
#
|
6
|
+
|
7
|
+
# Start background thread to click popup windows
|
8
|
+
# Warning:
|
9
|
+
# Make browser window active
|
10
|
+
# Don't mouse your mouse to focus other window during test execution
|
11
|
+
def check_for_popups
|
12
|
+
autoit = WIN32OLE.new('AutoItX3.Control')
|
13
|
+
#
|
14
|
+
# Do forever - assumes popups could occur anywhere/anytime in your
|
15
|
+
# application.
|
16
|
+
loop do
|
17
|
+
# Look for window with given title. Give up after 1 second.
|
18
|
+
ret = autoit.WinWait('Windows Internet Explorer', '', 1)
|
19
|
+
#
|
20
|
+
# If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).
|
21
|
+
if (ret==1) then
|
22
|
+
autoit.Send('{enter}')
|
23
|
+
end
|
24
|
+
#
|
25
|
+
# Take a rest to avoid chewing up cycles and give another thread a go.
|
26
|
+
# Then resume the loop.
|
27
|
+
sleep(3)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Check for "Security Information" and "Security Alert" alert popup, click 'Yes'
|
33
|
+
#
|
34
|
+
# Usage: For individual test suite
|
35
|
+
#
|
36
|
+
# before(:all) do
|
37
|
+
# $popup = Thread.new { check_for_alerts }
|
38
|
+
# open_in_browser
|
39
|
+
# ...
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# after(:all) do
|
43
|
+
# close_browser
|
44
|
+
# Thread.kill($popup)
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# or for all tests,
|
48
|
+
# $popup = Thread.new { check_for_alerts }
|
49
|
+
# at_exit{ Thread.kill($popup) }
|
50
|
+
def check_for_security_alerts
|
51
|
+
autoit = WIN32OLE.new('AutoItX3.Control')
|
52
|
+
loop do
|
53
|
+
["Security Alert", "Security Information"].each do |win_title|
|
54
|
+
ret = autoit.WinWait(win_title, '', 1)
|
55
|
+
if (ret==1) then
|
56
|
+
autoit.Send('{Y}')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
sleep(3)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def verify_alert(title = "Microsoft Internet Explorer", button = "OK")
|
64
|
+
if is_windows? && !is_firefox?
|
65
|
+
WIN32OLE.new('AutoItX3.Control').ControlClick(title, '', button)
|
66
|
+
else
|
67
|
+
raise "This function only supports IE"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def click_button_in_security_information_popup(button = "&Yes")
|
72
|
+
verify_alert("Security Information", "", button)
|
73
|
+
end
|
74
|
+
alias click_security_information_popup click_button_in_security_information_popup
|
75
|
+
|
76
|
+
def click_button_in_security_alert_popup(button = "&Yes")
|
77
|
+
verify_alert("Security Alert", "", button)
|
78
|
+
end
|
79
|
+
alias click_security_alert_popup click_button_in_security_alert_popup
|
80
|
+
|
81
|
+
def click_button_in_javascript_popup(button = "OK")
|
82
|
+
verify_alert()
|
83
|
+
end
|
84
|
+
alias click_javascript_popup click_button_in_javascript_popup
|
85
|
+
|
86
|
+
##
|
87
|
+
# This only works for IEs
|
88
|
+
# Cons:
|
89
|
+
# - Slow
|
90
|
+
# - only works in IE
|
91
|
+
# - does not work for security alert ?
|
92
|
+
def ie_popup_clicker(button_name = "OK", max_wait = 15)
|
93
|
+
require 'watir/contrib/enabled_popup'
|
94
|
+
require 'win32ole'
|
95
|
+
hwnd = ie.enabled_popup(15)
|
96
|
+
if (hwnd) #yeah! a popup
|
97
|
+
popup = WinClicker.new
|
98
|
+
popup.makeWindowActive(hwnd) #Activate the window.
|
99
|
+
popup.clickWindowsButton_hwnd(hwnd, button_name) #Click the button
|
100
|
+
#popup.clickWindowsButton(/Internet/,button_name,30)
|
101
|
+
popup = nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def click_popup_window(button, wait_time= 9, user_input=nil )
|
106
|
+
@web_browser.start_clicker(button, wait_time, user_input)
|
107
|
+
sleep 0.5
|
108
|
+
end
|
109
|
+
# run a separate process waiting for the popup window to click
|
110
|
+
#
|
111
|
+
#
|
112
|
+
def prepare_to_click_button_in_popup(button = "OK", wait_time = 3)
|
113
|
+
# !@web_browser.is_firefox?
|
114
|
+
# TODO: firefox is OK
|
115
|
+
if RUBY_PLATFORM =~ /mswin/ then
|
116
|
+
start_checking_js_dialog(button, wait_time)
|
117
|
+
else
|
118
|
+
raise "this only support on Windows and on IE"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Start a background process to click the button on a javascript popup window
|
123
|
+
def start_checking_js_dialog(button = "OK", wait_time = 3)
|
124
|
+
w = WinClicker.new
|
125
|
+
longName = File.expand_path(File.dirname(__FILE__)).gsub("/", "\\" )
|
126
|
+
shortName = w.getShortFileName(longName)
|
127
|
+
c = "start ruby #{shortName}\\clickJSDialog.rb #{button} #{wait_time} "
|
128
|
+
w.winsystem(c)
|
129
|
+
w = nil
|
130
|
+
end
|
131
|
+
|
132
|
+
# Click the button in javascript popup dialog
|
133
|
+
# Usage:
|
134
|
+
# click_button_in_popup_after { click_link('Cancel')}
|
135
|
+
# click_button_in_popup_after("OK") { click_link('Cancel')}
|
136
|
+
#
|
137
|
+
def click_button_in_popup_after(options = {:button => "OK", :wait_time => 3}, &block)
|
138
|
+
if is_windows? then
|
139
|
+
start_checking_js_dialog(options[:button], options[:wait_time])
|
140
|
+
yield
|
141
|
+
else
|
142
|
+
raise "this only support on Windows and on IE"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|