rwebunit 0.9.4 → 1.0.3
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.
- data/CHANGELOG +228 -168
- data/MIT-LICENSE +1 -1
- data/README +32 -29
- data/Rakefile +5 -4
- data/lib/rspec_extensions.rb +10 -2
- data/lib/rwebunit.rb +8 -3
- data/lib/rwebunit/assert.rb +25 -24
- data/lib/rwebunit/clickJSDialog.rb +15 -0
- data/lib/rwebunit/context.rb +24 -24
- data/lib/rwebunit/driver.rb +297 -33
- data/lib/rwebunit/itest_plugin.rb +47 -0
- data/lib/rwebunit/matchers/contains_text.rb +37 -0
- data/lib/rwebunit/rspec_helper.rb +140 -128
- data/lib/rwebunit/test_utils.rb +98 -88
- data/lib/rwebunit/{web_tester.rb → web_browser.rb} +433 -510
- data/lib/rwebunit/web_page.rb +96 -99
- data/lib/rwebunit/web_testcase.rb +36 -36
- data/lib/watir_extensions.rb +65 -0
- data/test/mock_page.rb +8 -0
- data/test/setup.rb +10 -0
- data/test/test.html +129 -0
- data/test/test_assert.rb +64 -0
- data/test/test_driver.rb +23 -5
- metadata +24 -14
- data/sample/README.txt +0 -21
- data/sample/kangxi_home_webtest.rb +0 -37
- data/sample/kangxi_httpcaller_webtest.rb +0 -33
- data/sample/kangxi_pages.rb +0 -62
- data/sample/kangxi_xml_formatter_webtest.rb +0 -44
- data/sample/rwebunit_home_testcase.rb +0 -22
- data/sample/sample_rwebunit_test.rb +0 -15
- data/sample/sample_rwebunit_testcase.rb +0 -22
- data/sample/sample_watir_test.rb +0 -17
data/Rakefile
CHANGED
@@ -36,7 +36,7 @@ Rake::RDocTask.new { |rdoc|
|
|
36
36
|
spec = Gem::Specification.new do |s|
|
37
37
|
s.platform= Gem::Platform::RUBY
|
38
38
|
s.name = "rwebunit"
|
39
|
-
s.version = "0.
|
39
|
+
s.version = "1.0.3"
|
40
40
|
s.summary = "An wrap of WATIR/FireWatir for functional testing of web applications"
|
41
41
|
# s.description = ""
|
42
42
|
|
@@ -56,9 +56,10 @@ spec = Gem::Specification.new do |s|
|
|
56
56
|
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
57
57
|
s.files = s.files + Dir.glob( "sample/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
58
58
|
s.files = s.files + Dir.glob( "docs/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
59
|
-
s.add_dependency(%q<rspec>, ["
|
60
|
-
|
61
|
-
# s.add_dependency("
|
59
|
+
s.add_dependency(%q<rspec>, ["= 1.1.4"])
|
60
|
+
s.add_dependency("commonwatir", ">= 1.6.2")
|
61
|
+
# s.add_dependency("watir", ">= 1.6.2")
|
62
|
+
# s.add_dependency("firewatir", ">= 1.6.2")
|
62
63
|
end
|
63
64
|
|
64
65
|
Rake::GemPackageTask.new(spec) do |pkg|
|
data/lib/rspec_extensions.rb
CHANGED
@@ -4,6 +4,8 @@ module Spec
|
|
4
4
|
|
5
5
|
alias :spec :describe
|
6
6
|
alias :specification :describe
|
7
|
+
alias :test_suite :describe
|
8
|
+
alias :suite :describe
|
7
9
|
|
8
10
|
end
|
9
11
|
end
|
@@ -16,6 +18,8 @@ module Spec
|
|
16
18
|
|
17
19
|
alias_method :scenario, :it
|
18
20
|
alias_method :story, :it
|
21
|
+
alias_method :test_case, :it
|
22
|
+
alias_method :test, :it
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -24,11 +28,11 @@ module Spec
|
|
24
28
|
module Runner
|
25
29
|
class SpecParser
|
26
30
|
def example_group_at_line(source, line_number)
|
27
|
-
find_above(source, line_number, /^\s*(context|describe|specification|spec)\s+(.*)\s+do/)
|
31
|
+
find_above(source, line_number, /^\s*(context|describe|specification|spec|test_suite|suite)\s+(.*)\s+do/)
|
28
32
|
end
|
29
33
|
|
30
34
|
def example_at_line(source, line_number)
|
31
|
-
find_above(source, line_number, /^\s*(specify|it|story|scenario)\s+(.*)\s+do/)
|
35
|
+
find_above(source, line_number, /^\s*(specify|it|story|scenario|test_case|test)\s+(.*)\s+do/)
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
@@ -59,11 +63,15 @@ module Spec
|
|
59
63
|
return line if line =~ /(should_not|should)_receive/
|
60
64
|
|
61
65
|
line.gsub!(/(^\s*)context([\s*|\(]['|"|A-Z])/, '\1describe\2')
|
66
|
+
line.gsub!(/(^\s*)test_suite([\s*|\(]['|"|A-Z])/, '\1describe\2')
|
67
|
+
line.gsub!(/(^\s*)suite([\s*|\(]['|"|A-Z])/, '\1describe\2')
|
62
68
|
line.gsub!(/(^\s*)spec([\s*|\(]['|"|A-Z])/, '\1describe\2') #new
|
63
69
|
line.gsub!(/(^\s*)specification([\s*|\(]['|"|A-Z])/, '\1describe\2') #new
|
64
70
|
line.gsub!(/(^\s*)specify([\s*|\(]['|"|A-Z])/, '\1it\2')
|
65
71
|
line.gsub!(/(^\s*)scenario([\s*|\(]['|"|A-Z])/, '\1it\2') #new
|
66
72
|
line.gsub!(/(^\s*)story([\s*|\(]['|"|A-Z])/, '\1it\2') #new
|
73
|
+
line.gsub!(/(^\s*)test_case([\s*|\(]['|"|A-Z])/, '\1it\2') #new
|
74
|
+
line.gsub!(/(^\s*)test([\s*|\(]['|"|A-Z])/, '\1it\2') #new
|
67
75
|
line.gsub!(/(^\s*)context_setup(\s*[do|\{])/, '\1before(:all)\2')
|
68
76
|
line.gsub!(/(^\s*)context_teardown(\s*[do|\{])/, '\1after(:all)\2')
|
69
77
|
line.gsub!(/(^\s*)setup(\s*[do|\{])/, '\1before(:each)\2')
|
data/lib/rwebunit.rb
CHANGED
@@ -11,8 +11,10 @@ rescue LoadError => no_as1_err
|
|
11
11
|
# active_support 2.0 loaded error
|
12
12
|
end
|
13
13
|
require 'active_support/core_ext'
|
14
|
-
|
15
14
|
require 'spec'
|
15
|
+
require 'hpricot' # for parsing HTML
|
16
|
+
|
17
|
+
RWEBUNIT_VERSION = "1.0.3"
|
16
18
|
|
17
19
|
# Extra full path to load libraries
|
18
20
|
require File.dirname(__FILE__) + "/rwebunit/test_utils"
|
@@ -20,9 +22,12 @@ require File.dirname(__FILE__) + "/rwebunit/web_page"
|
|
20
22
|
require File.dirname(__FILE__) + "/rwebunit/assert"
|
21
23
|
#This cause some unit test loaded, to use it, load specifiically
|
22
24
|
#require File.dirname(__FILE__) + "/rwebunit/web_testcase"
|
23
|
-
require File.dirname(__FILE__) + "/rwebunit/
|
25
|
+
require File.dirname(__FILE__) + "/rwebunit/itest_plugin"
|
26
|
+
require File.dirname(__FILE__) + "/rwebunit/web_browser"
|
27
|
+
require File.dirname(__FILE__) + "/rwebunit/driver"
|
24
28
|
require File.dirname(__FILE__) + "/rwebunit/context"
|
25
29
|
require File.dirname(__FILE__) + "/rwebunit/driver"
|
26
30
|
require File.dirname(__FILE__) + "/rwebunit/rspec_helper"
|
27
31
|
require File.dirname(__FILE__) + "/rspec_extensions"
|
28
|
-
|
32
|
+
require File.dirname(__FILE__) + "/watir_extensions"
|
33
|
+
require File.dirname(__FILE__) + "/rwebunit/matchers/contains_text"
|
data/lib/rwebunit/assert.rb
CHANGED
@@ -13,11 +13,11 @@ module RWebUnit
|
|
13
13
|
##
|
14
14
|
# text
|
15
15
|
def assert_text_present(text)
|
16
|
-
assert((@
|
16
|
+
assert((@web_browser.page_source.include? text), 'expected text: ' + text + ' not found')
|
17
17
|
end
|
18
18
|
|
19
19
|
def assert_text_not_present(text)
|
20
|
-
assert(!(@
|
20
|
+
assert(!(@web_browser.page_source.include? text), 'expected text: ' + text + ' found')
|
21
21
|
end
|
22
22
|
|
23
23
|
def assert_text_in_table(tableId, text)
|
@@ -52,7 +52,7 @@ module RWebUnit
|
|
52
52
|
##
|
53
53
|
# Checkbox
|
54
54
|
def assert_checkbox_not_selected(checkBoxName)
|
55
|
-
@
|
55
|
+
@web_browser.checkboxes.each { |checkbox|
|
56
56
|
if (checkbox.name == checkBoxName) then
|
57
57
|
assert(!checkbox.isSet?, "Checkbox #{checkBoxName} checked unexpected")
|
58
58
|
end
|
@@ -60,7 +60,7 @@ module RWebUnit
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def assert_checkbox_selected(checkBoxName)
|
63
|
-
@
|
63
|
+
@web_browser.checkboxes.each { |checkbox|
|
64
64
|
if (checkbox.name == checkBoxName) then
|
65
65
|
assert(checkbox.isSet?, "Checkbox #{checkBoxName} not checked")
|
66
66
|
end
|
@@ -70,7 +70,7 @@ module RWebUnit
|
|
70
70
|
##
|
71
71
|
# select
|
72
72
|
def assert_option_value_not_present(selectName, optionValue)
|
73
|
-
@
|
73
|
+
@web_browser.select_lists.each { |select|
|
74
74
|
continue unless select.name == selectName
|
75
75
|
select.o.each do |option| # items in the list
|
76
76
|
assert(!(option.value == optionValue), "unexpected select option: #{optionValue} for #{selectName} found")
|
@@ -79,7 +79,7 @@ module RWebUnit
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def assert_option_not_present(selectName, optionLabel)
|
82
|
-
@
|
82
|
+
@web_browser.select_lists.each { |select|
|
83
83
|
next unless select.name == selectName
|
84
84
|
select.o.each do |option| # items in the list
|
85
85
|
assert(!(option.text == optionLabel), "unexpected select option: #{optionLabel} for #{selectName} found")
|
@@ -88,7 +88,7 @@ module RWebUnit
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def assert_option_value_present(selectName, optionValue)
|
91
|
-
@
|
91
|
+
@web_browser.select_lists.each { |select|
|
92
92
|
next unless select.name == selectName
|
93
93
|
select.o.each do |option| # items in the list
|
94
94
|
return if option.value == optionValue
|
@@ -98,7 +98,7 @@ module RWebUnit
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def assert_option_present(selectName, optionLabel)
|
101
|
-
@
|
101
|
+
@web_browser.select_lists.each { |select|
|
102
102
|
next unless select.name == selectName
|
103
103
|
select.o.each do |option| # items in the list
|
104
104
|
return if option.text == optionLabel
|
@@ -108,7 +108,7 @@ module RWebUnit
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def assert_option_equals(selectName, optionLabel)
|
111
|
-
@
|
111
|
+
@web_browser.select_lists.each { |select|
|
112
112
|
next unless select.name == selectName
|
113
113
|
select.o.each do |option| # items in the list
|
114
114
|
if (option.text == optionLabel) then
|
@@ -119,7 +119,7 @@ module RWebUnit
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def assert_option_value_equals(selectName, optionValue)
|
122
|
-
@
|
122
|
+
@web_browser.select_lists.each { |select|
|
123
123
|
next unless select.name == selectName
|
124
124
|
assert_equal(select.value, optionValue, "Select #{selectName}'s value is not equal to expected: '#{optionValue}'")
|
125
125
|
}
|
@@ -130,7 +130,7 @@ module RWebUnit
|
|
130
130
|
|
131
131
|
# radioGroup is the name field, radio options 'value' field
|
132
132
|
def assert_radio_option_not_present(radioGroup, radioOption)
|
133
|
-
@
|
133
|
+
@web_browser.radios.each { |radio|
|
134
134
|
if (radio.name == radioGroup) then
|
135
135
|
assert(!(radioOption == radio.value), "unexpected radio option: " + radioOption + " found")
|
136
136
|
end
|
@@ -138,14 +138,14 @@ module RWebUnit
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def assert_radio_option_present(radioGroup, radioOption)
|
141
|
-
@
|
141
|
+
@web_browser.radios.each { |radio|
|
142
142
|
return if (radio.name == radioGroup) and (radioOption == radio.value)
|
143
143
|
}
|
144
144
|
fail("can't find the radio option : '#{radioOption}'")
|
145
145
|
end
|
146
146
|
|
147
147
|
def assert_radio_option_selected(radioGroup, radioOption)
|
148
|
-
@
|
148
|
+
@web_browser.radios.each { |radio|
|
149
149
|
if (radio.name == radioGroup and radioOption == radio.value) then
|
150
150
|
assert(radio.isSet?, "Radio button #{radioGroup}-[#{radioOption}] not checked")
|
151
151
|
end
|
@@ -153,7 +153,7 @@ module RWebUnit
|
|
153
153
|
end
|
154
154
|
|
155
155
|
def assert_radio_option_not_selected(radioGroup, radioOption)
|
156
|
-
@
|
156
|
+
@web_browser.radios.each { |radio|
|
157
157
|
if (radio.name == radioGroup and radioOption == radio.value) then
|
158
158
|
assert(!radio.isSet?, "Radio button #{radioGroup}-[#{radioOption}] checked unexpected")
|
159
159
|
end
|
@@ -163,26 +163,26 @@ module RWebUnit
|
|
163
163
|
##
|
164
164
|
# Button
|
165
165
|
def assert_button_not_present(buttonId)
|
166
|
-
@
|
166
|
+
@web_browser.buttons.each { |button|
|
167
167
|
assert(button.id != buttonId, "unexpected button id: #{buttonId} found")
|
168
168
|
}
|
169
169
|
end
|
170
170
|
|
171
171
|
def assert_button_not_present_with_text(text)
|
172
|
-
@
|
172
|
+
@web_browser.buttons.each { |button|
|
173
173
|
assert(button.value != text, "unexpected button id: #{text} found")
|
174
174
|
}
|
175
175
|
end
|
176
176
|
|
177
177
|
def assert_button_present(buttonID)
|
178
|
-
@
|
178
|
+
@web_browser.buttons.each { |button|
|
179
179
|
return if buttonID == button.id
|
180
180
|
}
|
181
181
|
assert(false, "can't find the button with id: #{buttonID}")
|
182
182
|
end
|
183
183
|
|
184
184
|
def assert_button_present_with_text(buttonText)
|
185
|
-
@
|
185
|
+
@web_browser.buttons.each { |button|
|
186
186
|
return if buttonText == button.value
|
187
187
|
}
|
188
188
|
assert(false, "can't find the button with text: #{buttonText}")
|
@@ -191,33 +191,33 @@ module RWebUnit
|
|
191
191
|
##
|
192
192
|
# Link
|
193
193
|
def assert_link_present_with_exact(linkText)
|
194
|
-
@
|
194
|
+
@web_browser.links.each { |link|
|
195
195
|
return if linkText == link.text
|
196
196
|
}
|
197
197
|
fail( "can't find the link with text: #{linkText}")
|
198
198
|
end
|
199
199
|
|
200
200
|
def assert_link_not_present_with_exact(linkText)
|
201
|
-
@
|
201
|
+
@web_browser.links.each { |link|
|
202
202
|
assert(linkText != link.text, "unexpected link (exact): #{linkText} found")
|
203
203
|
}
|
204
204
|
end
|
205
205
|
|
206
206
|
def assert_link_present_with_text(linkText)
|
207
|
-
@
|
207
|
+
@web_browser.links.each { |link|
|
208
208
|
return if link.text.include?(linkText)
|
209
209
|
}
|
210
210
|
fail( "can't find the link containing text: #{linkText}")
|
211
211
|
end
|
212
212
|
|
213
213
|
def assert_link_not_present_with_text(linkText)
|
214
|
-
@
|
214
|
+
@web_browser.links.each { |link|
|
215
215
|
assert(!link.text.include?(linkText), "unexpected link containing: #{linkText} found")
|
216
216
|
}
|
217
217
|
end
|
218
218
|
|
219
219
|
def assert_text_present_in_text_field(textfieldName, text, msg = nil)
|
220
|
-
@
|
220
|
+
@web_browser.textfields.each { |textfield|
|
221
221
|
if (textfield.name == textfieldName) then
|
222
222
|
assert(text_field.value.include?(text), "text: #{text} not in text field: " + textfieldName)
|
223
223
|
end
|
@@ -226,8 +226,9 @@ module RWebUnit
|
|
226
226
|
|
227
227
|
# assertions
|
228
228
|
def assert_title_equals(title)
|
229
|
-
assert_equals(title, @
|
229
|
+
assert_equals(title, @web_browser.page_title)
|
230
230
|
end
|
231
|
+
alias assert_title assert_title_equals
|
231
232
|
|
232
233
|
def assert_equals(expected, actual, msg=nil)
|
233
234
|
assert(expected == actual, (msg.nil?) ? "Expected: #{expected} diff from actual: #{actual}" : msg)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#
|
2
|
+
# clickJSDialog.rb
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file contains the JS clicker when it runs as a separate process
|
6
|
+
require 'watir/winClicker'
|
7
|
+
|
8
|
+
button = "OK"
|
9
|
+
button = ARGV[0] unless ARGV[0] == nil
|
10
|
+
sleepTime = 0
|
11
|
+
sleepTime = ARGV[1] unless ARGV[1] == nil
|
12
|
+
|
13
|
+
clicker= WinClicker.new
|
14
|
+
result = clicker.clickJavaScriptDialog( button )
|
15
|
+
clicker = nil
|
data/lib/rwebunit/context.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
#***********************************************************
|
2
|
-
#* Copyright (c) 2006, 2007 Zhimin Zhan.
|
3
|
-
#* Distributed open-source, see full license in MIT-LICENSE
|
4
|
-
#***********************************************************
|
5
|
-
|
6
|
-
module RWebUnit
|
7
|
-
|
8
|
-
##
|
9
|
-
# Store test optionns
|
10
|
-
#
|
11
|
-
class Context
|
12
|
-
attr_accessor :base_url
|
13
|
-
|
14
|
-
def initialize(base_url)
|
15
|
-
set_base_url(base_url)
|
16
|
-
end
|
17
|
-
|
18
|
-
def set_base_url(baseUrl)
|
19
|
-
@base_url = baseUrl
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
1
|
+
#***********************************************************
|
2
|
+
#* Copyright (c) 2006, 2007 Zhimin Zhan.
|
3
|
+
#* Distributed open-source, see full license in MIT-LICENSE
|
4
|
+
#***********************************************************
|
5
|
+
|
6
|
+
module RWebUnit
|
7
|
+
|
8
|
+
##
|
9
|
+
# Store test optionns
|
10
|
+
#
|
11
|
+
class Context
|
12
|
+
attr_accessor :base_url
|
13
|
+
|
14
|
+
def initialize(base_url)
|
15
|
+
set_base_url(base_url)
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_base_url(baseUrl)
|
19
|
+
@base_url = baseUrl
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/rwebunit/driver.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# The Mixin is normally included in the spec/tests and pages, provide
|
2
1
|
# convenient methods to drive the browser.
|
3
2
|
#
|
4
3
|
# Instead of
|
@@ -6,17 +5,28 @@
|
|
6
5
|
# You can just use
|
7
6
|
# click_button("submit")
|
8
7
|
#
|
8
|
+
require File.join(File.dirname(__FILE__), 'itest_plugin')
|
9
|
+
require 'timeout'
|
9
10
|
|
10
11
|
module RWebUnit
|
11
12
|
module Driver
|
13
|
+
include RWebUnit::ITestPlugin
|
14
|
+
|
15
|
+
def browser
|
16
|
+
@web_browser
|
17
|
+
end
|
12
18
|
|
13
19
|
# Verify the next page following an operation.
|
14
20
|
#
|
15
21
|
# Typical usage:
|
16
22
|
# login_page.click_login
|
17
23
|
# expect_page HomePage
|
18
|
-
def expect_page(page_clazz)
|
19
|
-
|
24
|
+
def expect_page(page_clazz, argument = nil)
|
25
|
+
if argument
|
26
|
+
page_clazz.new(@web_browser, argument)
|
27
|
+
else
|
28
|
+
page_clazz.new(@web_browser)
|
29
|
+
end
|
20
30
|
end
|
21
31
|
|
22
32
|
# Using Ruby block syntax to create interesting domain specific language,
|
@@ -69,36 +79,48 @@ module RWebUnit
|
|
69
79
|
alias fail_safe failsafe
|
70
80
|
|
71
81
|
def context
|
72
|
-
@
|
82
|
+
@web_browser.context
|
73
83
|
end
|
74
84
|
|
75
85
|
def begin_at(url)
|
76
|
-
|
86
|
+
dump_caller_stack
|
87
|
+
@web_browser.begin_at(url)
|
77
88
|
end
|
78
89
|
|
79
90
|
def ie
|
80
|
-
@
|
91
|
+
@web_browser.ie
|
92
|
+
end
|
93
|
+
|
94
|
+
def is_firefox?
|
95
|
+
@web_browser.is_firefox?
|
96
|
+
end
|
97
|
+
|
98
|
+
def firefox
|
99
|
+
@web_browser.firefox
|
81
100
|
end
|
82
101
|
|
83
102
|
def close_browser
|
84
|
-
|
103
|
+
dump_caller_stack
|
104
|
+
@web_browser.close_browser unless $ITEST2_LEAVE_BROWSER_OPEN_AFTER_RUN
|
85
105
|
end
|
86
106
|
alias close_ie close_browser
|
87
107
|
|
88
|
-
[:go_back, :go_forward, :refresh].each do |method|
|
89
|
-
define_method(method) do
|
90
|
-
@web_tester.send(method)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
alias refresh_page refresh
|
94
108
|
|
95
109
|
def goto_page(page)
|
96
110
|
operation_delay
|
97
|
-
|
111
|
+
dump_caller_stack
|
112
|
+
@web_browser.goto_page(page);
|
98
113
|
end
|
114
|
+
alias visit goto_page
|
99
115
|
|
100
|
-
def attach_browser(how, what)
|
101
|
-
|
116
|
+
def attach_browser(how, what, options = {})
|
117
|
+
options.merge!(:browser => is_firefox? ? "Firefox" : "IE")
|
118
|
+
begin
|
119
|
+
options.merge!(:base_url => browser.context.base_url)
|
120
|
+
rescue => e
|
121
|
+
puts "error to attach to browser: #{e}"
|
122
|
+
end
|
123
|
+
WebBrowser.attach_browser(how, what, options)
|
102
124
|
end
|
103
125
|
|
104
126
|
##
|
@@ -143,20 +165,28 @@ module RWebUnit
|
|
143
165
|
# p <p> (paragraph) tags, because
|
144
166
|
[:area, :button, :cell, :checkbox, :div, :form, :frame, :h1, :h2, :h3, :h4, :h5, :h6, :hidden, :image, :li, :link, :map, :pre, :row, :radio, :select_list, :span, :table, :text_field, :paragraph, :file_field, :label].each do |method|
|
145
167
|
define_method method do |*args|
|
146
|
-
|
168
|
+
dump_caller_stack
|
169
|
+
@web_browser.send(method, *args)
|
147
170
|
end
|
148
171
|
end
|
149
172
|
alias td cell
|
150
173
|
alias check_box checkbox # seems watir doc is wrong, checkbox not check_box
|
151
174
|
alias tr row
|
152
175
|
|
153
|
-
|
154
|
-
|
176
|
+
[:back, :forward, :refresh].each do |method|
|
177
|
+
define_method(method) do
|
178
|
+
dump_caller_stack
|
179
|
+
@web_browser.send(method)
|
180
|
+
end
|
155
181
|
end
|
182
|
+
alias refresh_page refresh
|
183
|
+
alias go_back back
|
184
|
+
alias go_forward forward
|
156
185
|
|
157
186
|
[:images, :links, :buttons, :select_lists, :checkboxes, :radios, :text_fields].each do |method|
|
158
187
|
define_method method do
|
159
|
-
|
188
|
+
dump_caller_stack
|
189
|
+
@web_browser.send(method)
|
160
190
|
end
|
161
191
|
end
|
162
192
|
|
@@ -164,10 +194,12 @@ module RWebUnit
|
|
164
194
|
#
|
165
195
|
# page.check_checkbox('bad_ones', 'Chicken Little')
|
166
196
|
# page.check_checkbox('good_ones', ['Cars', 'Toy Story'])
|
167
|
-
|
197
|
+
#
|
168
198
|
[:set_form_element, :click_link_with_text, :click_link_with_id, :submit, :click_button_with_id, :click_button_with_caption, :click_button_with_value, :click_radio_option, :clear_radio_option, :select_file_for_upload, :check_checkbox, :uncheck_checkbox, :select_option].each do |method|
|
169
199
|
define_method method do |*args|
|
170
|
-
|
200
|
+
dump_caller_stack
|
201
|
+
operation_delay
|
202
|
+
@web_browser.send(method, *args)
|
171
203
|
end
|
172
204
|
end
|
173
205
|
|
@@ -178,7 +210,19 @@ module RWebUnit
|
|
178
210
|
alias click_radio_button click_radio_option
|
179
211
|
alias clear_radio_button clear_radio_option
|
180
212
|
|
213
|
+
# for text field can be easier to be identified by attribute "id" instead of "name", not recommended though
|
214
|
+
def enter_text_with_id(textfield_id, value)
|
215
|
+
dump_caller_stack
|
216
|
+
operation_delay
|
217
|
+
text_field(:id, textfield_id).set(value)
|
218
|
+
end
|
219
|
+
|
220
|
+
def contains_text(text)
|
221
|
+
@web_browser.contains_text(text);
|
222
|
+
end
|
223
|
+
|
181
224
|
def click_button_with_image_src_contains(image_filename)
|
225
|
+
dump_caller_stack
|
182
226
|
operation_delay
|
183
227
|
found = nil
|
184
228
|
raise "no buttons in this page" if buttons.length <= 0
|
@@ -194,7 +238,7 @@ module RWebUnit
|
|
194
238
|
alias click_button_with_image click_button_with_image_src_contains
|
195
239
|
|
196
240
|
def new_popup_window(options)
|
197
|
-
@
|
241
|
+
@web_browser.new_popup_window(options)
|
198
242
|
end
|
199
243
|
|
200
244
|
# Wait for specific seconds for an Ajax update finish.
|
@@ -214,9 +258,9 @@ module RWebUnit
|
|
214
258
|
#
|
215
259
|
def ajax_wait_for_element(element_id, seconds, status='show', check_interval=2)
|
216
260
|
count = 0
|
217
|
-
check_interval =
|
261
|
+
check_interval = 1 if check_interval < 1 or check_interval > seconds
|
218
262
|
while count < (seconds / check_interval) do
|
219
|
-
search_indicator = @
|
263
|
+
search_indicator = @web_browser.element_by_id(element_id)
|
220
264
|
search_indicator_outer_html = search_indicator.outerHtml if search_indicator
|
221
265
|
if status == 'hide'
|
222
266
|
return true if search_indicator_outer_html and !search_indicator_outer_html.include?('style="DISPLAY: none"')
|
@@ -231,7 +275,7 @@ module RWebUnit
|
|
231
275
|
|
232
276
|
def wait_for_element(element_id, timeout = 30, interval = 0.5)
|
233
277
|
start_time = Time.now
|
234
|
-
until @
|
278
|
+
until @web_browser.element_by_id(element_id) do
|
235
279
|
sleep(interval)
|
236
280
|
if (Time.now - start_time) > timeout
|
237
281
|
raise RuntimeError, "failed to find element: #{element_id} for max #{timeout}"
|
@@ -239,17 +283,50 @@ module RWebUnit
|
|
239
283
|
end
|
240
284
|
end
|
241
285
|
|
242
|
-
|
286
|
+
# TODO: Firewatir does not suport retrieving style or outerHtml
|
287
|
+
# http://jira.openqa.org/browse/WTR-260
|
288
|
+
# http://code.google.com/p/firewatir/issues/detail?id=76
|
289
|
+
#
|
290
|
+
# Max timeout value is 10 minutes
|
291
|
+
#
|
292
|
+
def ajax_call_complete_after_element_hidden(elem_id, check_start = 0.5, timeout = 5, interval = 0.5, &block)
|
293
|
+
yield
|
294
|
+
sleep check_start # the time allowed to perform the coomplete
|
295
|
+
timeout = 10 * 60 if timeout > 10 * 600 or timeout <= 0
|
296
|
+
begin
|
297
|
+
Timeout::timeout(timeout) {
|
298
|
+
begin
|
299
|
+
elem = element_by_id(elem_id)
|
300
|
+
while elem do
|
301
|
+
puts "outer=>#{elem.outerHtml}|"
|
302
|
+
puts "style =>#{elem.attribute_value('style')}|"
|
303
|
+
sleep interval
|
304
|
+
elem = element_by_id(elem_id)
|
305
|
+
end
|
306
|
+
rescue => e
|
307
|
+
puts e
|
308
|
+
end
|
309
|
+
}
|
310
|
+
rescue Timeout::Error
|
311
|
+
# Too slow!!
|
312
|
+
raise "Too slow, wait max #{timeout} seconds, the element #{elem_id} still there"
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
# Warning: this does not work well with Firefox yet.
|
243
317
|
def element_text(elem_id)
|
244
|
-
@
|
318
|
+
@web_browser.element_value(elem_id)
|
245
319
|
end
|
246
320
|
|
321
|
+
def element_by_id(elem_id)
|
322
|
+
@web_browser.element_by_id(elem_id)
|
323
|
+
end
|
247
324
|
|
248
325
|
# ---
|
249
326
|
# For debugging
|
250
327
|
# ---
|
251
328
|
def dump_response(stream = nil)
|
252
|
-
@
|
329
|
+
@web_browser.dump_response(stream)
|
253
330
|
end
|
254
331
|
|
255
332
|
def save_current_page(to_dir = ENV['TEMP_DIR'] || "C:\\temp")
|
@@ -260,20 +337,207 @@ module RWebUnit
|
|
260
337
|
end
|
261
338
|
|
262
339
|
def click_popup_window(button, wait_time= 9, user_input=nil )
|
263
|
-
@
|
340
|
+
@web_browser.start_clicker(button, wait_time, user_input)
|
264
341
|
sleep 0.5
|
265
342
|
end
|
266
343
|
|
267
|
-
|
344
|
+
# return plain text view of page
|
345
|
+
def page_text
|
346
|
+
Hpricot(page_source).to_plain_text
|
347
|
+
end
|
348
|
+
|
349
|
+
def label_with_id(label_id)
|
350
|
+
label(:id, label_id).text
|
351
|
+
end
|
352
|
+
|
353
|
+
def span_with_id(span_id)
|
354
|
+
span(:id, span_id).text
|
355
|
+
end
|
356
|
+
|
357
|
+
def cell_with_id(cell_id)
|
358
|
+
cell(:id, cell_id).text
|
359
|
+
end
|
360
|
+
alias table_data_with_id cell_with_id
|
361
|
+
|
362
|
+
# run a separate process waiting for the popup window to click
|
363
|
+
#
|
364
|
+
#
|
365
|
+
def prepare_to_click_button_in_popup(button = "OK", wait_time = 3)
|
366
|
+
# !@web_browser.is_firefox?
|
367
|
+
# TODO: firefox is OK
|
368
|
+
if RUBY_PLATFORM =~ /mswin/ then
|
369
|
+
start_checking_js_dialog(button, wait_time)
|
370
|
+
else
|
371
|
+
raise "this only support on Windows and on IE"
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
# Start a background process to click the button on a javascript popup window
|
376
|
+
def start_checking_js_dialog(button = "OK", wait_time = 3)
|
377
|
+
w = WinClicker.new
|
378
|
+
longName = File.expand_path(File.dirname(__FILE__)).gsub("/", "\\" )
|
379
|
+
shortName = w.getShortFileName(longName)
|
380
|
+
c = "start ruby #{shortName}\\clickJSDialog.rb #{button} #{wait_time} "
|
381
|
+
w.winsystem(c)
|
382
|
+
w = nil
|
383
|
+
end
|
384
|
+
|
385
|
+
# Click the button in javascript popup dialog
|
386
|
+
# Usage:
|
387
|
+
# click_button_in_popup_after { click_link('Cancel')}
|
388
|
+
# click_button_in_popup_after("OK") { click_link('Cancel')}
|
389
|
+
#
|
390
|
+
def click_button_in_popup_after(options = {:button => "OK", :wait_time => 3}, &block)
|
391
|
+
if RUBY_PLATFORM =~ /mswin/ then
|
392
|
+
start_checking_js_dialog(options[:button], options[:wait_time])
|
393
|
+
yield
|
394
|
+
else
|
395
|
+
raise "this only support on Windows and on IE"
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
|
400
|
+
# Support of iTest to ajust the intervals between keystroke/mouse operations
|
268
401
|
def operation_delay
|
269
402
|
begin
|
270
|
-
if
|
271
|
-
|
403
|
+
if $ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY > 0 &&
|
404
|
+
$ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY < 30000 then # max 30 seconds
|
405
|
+
sleep($ITEST2_OPERATION_DELAY / 1000)
|
406
|
+
end
|
407
|
+
|
408
|
+
while $ITEST2_PAUSE
|
409
|
+
debug("Paused, waiting ...")
|
410
|
+
sleep 1
|
272
411
|
end
|
273
412
|
rescue => e
|
413
|
+
puts "Error on delaying: #{e}"
|
274
414
|
# ignore
|
275
415
|
end
|
276
416
|
end
|
277
417
|
|
418
|
+
|
419
|
+
def close_all_browsers
|
420
|
+
Watir::IE.close_all
|
421
|
+
end
|
422
|
+
|
423
|
+
def is_mac?
|
424
|
+
RUBY_PLATFORM.downcase.include?("darwin")
|
425
|
+
end
|
426
|
+
|
427
|
+
def is_windows?
|
428
|
+
RUBY_PLATFORM.downcase.include?("mswin")
|
429
|
+
end
|
430
|
+
|
431
|
+
def is_linux?
|
432
|
+
RUBY_PLATFORM.downcase.include?("linux")
|
433
|
+
end
|
434
|
+
|
435
|
+
# Start background thread to click popup windows
|
436
|
+
# Warning:
|
437
|
+
# Make browser window active
|
438
|
+
# Don't mouse your mouse to focus other window during test execution
|
439
|
+
def check_for_popups
|
440
|
+
autoit = WIN32OLE.new('AutoItX3.Control')
|
441
|
+
#
|
442
|
+
# Do forever - assumes popups could occur anywhere/anytime in your
|
443
|
+
# application.
|
444
|
+
loop do
|
445
|
+
# Look for window with given title. Give up after 1 second.
|
446
|
+
ret = autoit.WinWait('Windows Internet Explorer', '', 1)
|
447
|
+
#
|
448
|
+
# If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).
|
449
|
+
if (ret==1) then
|
450
|
+
autoit.Send('{enter}')
|
451
|
+
end
|
452
|
+
#
|
453
|
+
# Take a rest to avoid chewing up cycles and give another thread a go.
|
454
|
+
# Then resume the loop.
|
455
|
+
sleep(3)
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
##
|
460
|
+
# Check for "Security Information" and "Security Alert" alert popup, click 'Yes'
|
461
|
+
#
|
462
|
+
# Usage: For individual test suite
|
463
|
+
#
|
464
|
+
# before(:all) do
|
465
|
+
# $popup = Thread.new { check_for_alerts }
|
466
|
+
# open_in_browser
|
467
|
+
# ...
|
468
|
+
# end
|
469
|
+
#
|
470
|
+
# after(:all) do
|
471
|
+
# close_browser
|
472
|
+
# Thread.kill($popup)
|
473
|
+
# end
|
474
|
+
#
|
475
|
+
# or for all tests,
|
476
|
+
# $popup = Thread.new { check_for_alerts }
|
477
|
+
# at_exit{ Thread.kill($popup) }
|
478
|
+
def check_for_security_alerts
|
479
|
+
autoit = WIN32OLE.new('AutoItX3.Control')
|
480
|
+
loop do
|
481
|
+
["Security Alert", "Security Information"].each do |win_title|
|
482
|
+
ret = autoit.WinWait(win_title, '', 1)
|
483
|
+
if (ret==1) then
|
484
|
+
autoit.Send('{Y}')
|
485
|
+
end
|
486
|
+
end
|
487
|
+
sleep(3)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
def verify_alert(title = "Microsoft Internet Explorer", button = "OK")
|
492
|
+
if is_windows? && !is_firefox?
|
493
|
+
WIN32OLE.new('AutoItX3.Control').ControlClick(title, '', button)
|
494
|
+
else
|
495
|
+
raise "This function only supports IE"
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
def click_button_in_security_information_popup(button = "&Yes")
|
500
|
+
verify_alert("Security Information", "", button)
|
501
|
+
end
|
502
|
+
alias click_security_information_popup click_button_in_security_information_popup
|
503
|
+
|
504
|
+
def click_button_in_security_alert_popup(button = "&Yes")
|
505
|
+
verify_alert("Security Alert", "", button)
|
506
|
+
end
|
507
|
+
alias click_security_alert_popup click_button_in_security_alert_popup
|
508
|
+
|
509
|
+
def click_button_in_javascript_popup(button = "OK")
|
510
|
+
verify_alert()
|
511
|
+
end
|
512
|
+
alias click_javascript_popup click_button_in_javascript_popup
|
513
|
+
|
514
|
+
##
|
515
|
+
# This only works for IEs
|
516
|
+
# Cons:
|
517
|
+
# - Slow
|
518
|
+
# - only works in IE
|
519
|
+
# - does not work for security alert ?
|
520
|
+
def ie_popup_clicker(button_name = "OK", max_wait = 15)
|
521
|
+
require 'watir/contrib/enabled_popup'
|
522
|
+
require 'win32ole'
|
523
|
+
hwnd = ie.enabled_popup(15)
|
524
|
+
if (hwnd) #yeah! a popup
|
525
|
+
popup = WinClicker.new
|
526
|
+
popup.makeWindowActive(hwnd) #Activate the window.
|
527
|
+
popup.clickWindowsButton_hwnd(hwnd, button_name) #Click the button
|
528
|
+
#popup.clickWindowsButton(/Internet/,button_name,30)
|
529
|
+
popup = nil
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
##
|
534
|
+
# Convert :first to 1, :second to 2, and so on...
|
535
|
+
def symbol_to_sequence(symb)
|
536
|
+
value = { :zero => 0, :first => 1, :second => 2, :third => 3,
|
537
|
+
:fourth => 4, :fifth => 5, :sixth => 6, :seventh => 7,
|
538
|
+
:eighth => 8, :ninth => 9, :tenth => 10 }[symb]
|
539
|
+
return value || symb.to_i
|
540
|
+
end
|
541
|
+
|
278
542
|
end
|
279
543
|
end
|