rwebspec-webdriver 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/MIT-LICENSE +21 -0
- data/README +41 -0
- data/Rakefile +99 -0
- data/lib/rspec_extensions.rb +51 -0
- data/lib/rwebspec-webdriver.rb +52 -0
- data/lib/rwebspec/assert.rb +443 -0
- data/lib/rwebspec/clickJSDialog.rb +15 -0
- data/lib/rwebspec/context.rb +24 -0
- data/lib/rwebspec/database_checker.rb +74 -0
- data/lib/rwebspec/driver.rb +1009 -0
- data/lib/rwebspec/element_locator.rb +87 -0
- data/lib/rwebspec/load_test_helper.rb +172 -0
- data/lib/rwebspec/matchers/contains_text.rb +37 -0
- data/lib/rwebspec/popup.rb +147 -0
- data/lib/rwebspec/rspec_helper.rb +99 -0
- data/lib/rwebspec/test_script.rb +8 -0
- data/lib/rwebspec/test_utils.rb +217 -0
- data/lib/rwebspec/testwise_plugin.rb +83 -0
- data/lib/rwebspec/using_pages.rb +49 -0
- data/lib/rwebspec/web_browser.rb +742 -0
- data/lib/rwebspec/web_page.rb +108 -0
- data/lib/rwebspec/web_testcase.rb +38 -0
- data/lib/webdriver_extensions.rb +9 -0
- data/lib/window_script_extensions.rb +19 -0
- metadata +121 -0
@@ -0,0 +1,217 @@
|
|
1
|
+
#***********************************************************
|
2
|
+
#* Copyright (c) 2006, Zhimin Zhan.
|
3
|
+
#* Distributed open-source, see full license in MIT-LICENSE
|
4
|
+
#***********************************************************
|
5
|
+
|
6
|
+
class Array
|
7
|
+
|
8
|
+
def average
|
9
|
+
inject(0.0) { |sum, e| sum + e } / length
|
10
|
+
end
|
11
|
+
|
12
|
+
# NOTE might cause issues
|
13
|
+
# why it is removed total
|
14
|
+
def sum
|
15
|
+
inject(0.0) { |sum, e| sum + e }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# useful hekoer methods for testing
|
20
|
+
#
|
21
|
+
module RWebSpec
|
22
|
+
module Utils
|
23
|
+
|
24
|
+
# default date format returned is 29/12/2007.
|
25
|
+
# if supplied parameter is not '%m/%d/%Y' -> 12/29/2007
|
26
|
+
# Otherwise, "2007-12-29", which is most approiate date format
|
27
|
+
#
|
28
|
+
# %a - The abbreviated weekday name (``Sun'')
|
29
|
+
# %A - The full weekday name (``Sunday'')
|
30
|
+
# %b - The abbreviated month name (``Jan'')
|
31
|
+
# %B - The full month name (``January'')
|
32
|
+
# %c - The preferred local date and time representation
|
33
|
+
# %d - Day of the month (01..31)
|
34
|
+
# %H - Hour of the day, 24-hour clock (00..23)
|
35
|
+
# %I - Hour of the day, 12-hour clock (01..12)
|
36
|
+
# %j - Day of the year (001..366)
|
37
|
+
# %m - Month of the year (01..12)
|
38
|
+
# %M - Minute of the hour (00..59)
|
39
|
+
# %p - Meridian indicator (``AM'' or ``PM'')
|
40
|
+
# %S - Second of the minute (00..60)
|
41
|
+
# %U - Week number of the current year,
|
42
|
+
# starting with the first Sunday as the first
|
43
|
+
# day of the first week (00..53)
|
44
|
+
# %W - Week number of the current year,
|
45
|
+
# starting with the first Monday as the first
|
46
|
+
# day of the first week (00..53)
|
47
|
+
# %w - Day of the week (Sunday is 0, 0..6)
|
48
|
+
# %x - Preferred representation for the date alone, no time
|
49
|
+
# %X - Preferred representation for the time alone, no date
|
50
|
+
# %y - Year without a century (00..99)
|
51
|
+
# %Y - Year with century
|
52
|
+
# %Z - Time zone name
|
53
|
+
# %% - Literal ``%'' character
|
54
|
+
|
55
|
+
def today(format = nil)
|
56
|
+
format_date(Time.now, date_format(format))
|
57
|
+
end
|
58
|
+
alias getToday_AU today
|
59
|
+
alias getToday_US today
|
60
|
+
alias getToday today
|
61
|
+
|
62
|
+
|
63
|
+
def days_before(days, format = nil)
|
64
|
+
return nil if !(days.instance_of?(Fixnum))
|
65
|
+
format_date(Time.now - days * 24 * 3600, date_format(format))
|
66
|
+
end
|
67
|
+
|
68
|
+
def yesterday(format = nil)
|
69
|
+
days_before(1, date_format(format))
|
70
|
+
end
|
71
|
+
|
72
|
+
def days_from_now(days, format = nil)
|
73
|
+
return nil if !(days.instance_of?(Fixnum))
|
74
|
+
format_date(Time.now + days * 24 * 3600, date_format(format))
|
75
|
+
end
|
76
|
+
alias days_after days_from_now
|
77
|
+
|
78
|
+
def tomorrow(format = nil)
|
79
|
+
days_from_now(1, date_format(format))
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# return a random number >= min, but <= max
|
84
|
+
def random_number(min, max)
|
85
|
+
rand(max-min+1)+min
|
86
|
+
end
|
87
|
+
|
88
|
+
def random_boolean
|
89
|
+
return random_number(0, 1) == 1
|
90
|
+
end
|
91
|
+
|
92
|
+
def random_char(lowercase = true)
|
93
|
+
if lowercase
|
94
|
+
sprintf("%c", random_number(97, 122))
|
95
|
+
else
|
96
|
+
sprintf("%c", random_number(65, 90))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def random_digit()
|
101
|
+
sprintf("%c", random_number(48, 57))
|
102
|
+
end
|
103
|
+
|
104
|
+
def random_str(length, lowercase = true)
|
105
|
+
randomStr = ""
|
106
|
+
length.times {
|
107
|
+
randomStr += random_char(lowercase)
|
108
|
+
}
|
109
|
+
randomStr
|
110
|
+
end
|
111
|
+
|
112
|
+
# Return a random string in a rangeof pre-defined strings
|
113
|
+
def random_string_in(arr)
|
114
|
+
return nil if arr.empty?
|
115
|
+
index = random_number(0, arr.length-1)
|
116
|
+
arr[index]
|
117
|
+
end
|
118
|
+
alias random_string_in_collection random_string_in
|
119
|
+
|
120
|
+
|
121
|
+
WORDS = %w(alias consequatur aut perferendis sit voluptatem accusantium doloremque aperiam eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo aspernatur aut odit aut fugit sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt neque dolorem ipsum quia dolor sit amet consectetur adipisci velit sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem ut enim ad minima veniam quis nostrum exercitationem ullam corporis nemo enim ipsam voluptatem quia voluptas sit suscipit laboriosam nisi ut aliquid ex ea commodi consequatur quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae et iusto odio dignissimos ducimus qui blanditiis praesentium laudantium totam rem voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident sed ut perspiciatis unde omnis iste natus error similique sunt in culpa qui officia deserunt mollitia animi id est laborum et dolorum fuga et harum quidem rerum facilis est et expedita distinctio nam libero tempore cum soluta nobis est eligendi optio cumque nihil impedit quo porro quisquam est qui minus id quod maxime placeat facere possimus omnis voluptas assumenda est omnis dolor repellendus temporibus autem quibusdam et aut consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur at vero eos et accusamus officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae itaque earum rerum hic tenetur a sapiente delectus ut aut reiciendis voluptatibus maiores doloribus asperiores repellat)
|
122
|
+
|
123
|
+
# Pick a random value out of a given range.
|
124
|
+
def value_in_range(range)
|
125
|
+
case range.first
|
126
|
+
when Integer then number_in_range(range)
|
127
|
+
when Time then time_in_range(range)
|
128
|
+
when Date then date_in_range(range)
|
129
|
+
else range.to_a.rand
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Generate a given number of words. If a range is passed, it will generate
|
134
|
+
# a random number of words within that range.
|
135
|
+
def words(total)
|
136
|
+
(1..interpret_value(total)).map { WORDS[random_number(0, total)] }.join(' ')
|
137
|
+
end
|
138
|
+
|
139
|
+
# Generate a given number of sentences. If a range is passed, it will generate
|
140
|
+
# a random number of sentences within that range.
|
141
|
+
def sentences(total)
|
142
|
+
(1..interpret_value(total)).map do
|
143
|
+
words(5..20).capitalize
|
144
|
+
end.join('. ')
|
145
|
+
end
|
146
|
+
|
147
|
+
# Generate a given number of paragraphs. If a range is passed, it will generate
|
148
|
+
# a random number of paragraphs within that range.
|
149
|
+
def paragraphs(total)
|
150
|
+
(1..interpret_value(total)).map do
|
151
|
+
sentences(3..8).capitalize
|
152
|
+
end.join("\n\n")
|
153
|
+
end
|
154
|
+
|
155
|
+
# If an array or range is passed, a random value will be selected to match.
|
156
|
+
# All other values are simply returned.
|
157
|
+
def interpret_value(value)
|
158
|
+
case value
|
159
|
+
when Array then value.rand
|
160
|
+
when Range then value_in_range(value)
|
161
|
+
else value
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def time_in_range(range)
|
168
|
+
Time.at number_in_range(Range.new(range.first.to_i, range.last.to_i, rangee.exclude_end?))
|
169
|
+
end
|
170
|
+
|
171
|
+
def date_in_range(range)
|
172
|
+
Date.jd number_in_range(Range.new(range.first.jd, range.last.jd, range.exclude_end?))
|
173
|
+
end
|
174
|
+
|
175
|
+
def number_in_range(range)
|
176
|
+
if range.exclude_end?
|
177
|
+
rand(range.last - range.first) + range.first
|
178
|
+
else
|
179
|
+
rand((range.last+1) - range.first) + range.first
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def format_date(date, date_format = '%d/%m/%Y')
|
184
|
+
date.strftime(date_format)
|
185
|
+
end
|
186
|
+
|
187
|
+
def date_format(format_argument)
|
188
|
+
if format_argument.nil? then
|
189
|
+
get_locale_date_format(default_locale)
|
190
|
+
elsif format_argument.class == Symbol then
|
191
|
+
get_locale_date_format(format_argument)
|
192
|
+
elsif format_argument.class == String then
|
193
|
+
format_argument
|
194
|
+
else
|
195
|
+
# invalid input, use default
|
196
|
+
get_locale_date_format(default_date_format)
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
def get_locale_date_format(locale)
|
202
|
+
case locale
|
203
|
+
when :us
|
204
|
+
"%m/%d/%Y"
|
205
|
+
when :au, :uk
|
206
|
+
"%d/%m/%Y"
|
207
|
+
else
|
208
|
+
"%Y-%m-%d"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def default_locale
|
213
|
+
return :au
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module RWebSpec
|
4
|
+
module TestWisePlugin
|
5
|
+
|
6
|
+
def debug(message)
|
7
|
+
connect_to_testwise(" DEBUG", message.to_s + "\r\n") if $RUN_IN_TESTWISE && message
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
# Support of iTest to ajust the intervals between keystroke/mouse operations
|
12
|
+
def operation_delay
|
13
|
+
begin
|
14
|
+
if $ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY > 0 &&
|
15
|
+
$ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY < 30000 then # max 30 seconds
|
16
|
+
sleep($ITEST2_OPERATION_DELAY / 1000)
|
17
|
+
end
|
18
|
+
|
19
|
+
while $ITEST2_PAUSE
|
20
|
+
debug("Paused, waiting ...")
|
21
|
+
sleep 1
|
22
|
+
end
|
23
|
+
rescue => e
|
24
|
+
puts "Error on delaying: #{e}"
|
25
|
+
# ignore
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def notify_screenshot_location(image_file_path)
|
30
|
+
connect_to_testwise(" SHOT", image_file_path)
|
31
|
+
end
|
32
|
+
|
33
|
+
# find out the line (and file) the execution is on, and notify iTest via Socket
|
34
|
+
def dump_caller_stack
|
35
|
+
return unless $ITEST2_TRACE_EXECUTION
|
36
|
+
begin
|
37
|
+
trace_lines = []
|
38
|
+
trace_file = nil
|
39
|
+
found_first_spec_reference = false
|
40
|
+
caller.each_with_index do |position, idx|
|
41
|
+
next unless position =~ /\A(.*?):(\d+)/
|
42
|
+
trace_file = $1
|
43
|
+
if trace_file =~ /(_spec|_test|_rwebspec)\.rb\s*$/
|
44
|
+
found_first_spec_reference = true
|
45
|
+
trace_lines << position
|
46
|
+
break
|
47
|
+
end
|
48
|
+
trace_lines << position
|
49
|
+
break if trace_file =~ /example\/example_methods\.rb$/ or trace_file =~ /example\/example_group_methods\.rb$/
|
50
|
+
break if trace_lines.size > 10
|
51
|
+
# TODO: send multiple trace to be parse with pages.rb
|
52
|
+
# break if trace_file =~ /example\/example_methods\.rb$/ or trace_file =~ /example\/example_group_methods\.rb$/ or trace_file =~ /driver\.rb$/ or trace_file =~ /timeout\.rb$/ # don't include rspec or ruby trace
|
53
|
+
end
|
54
|
+
|
55
|
+
# (trace_file.include?("_spec.rb") || trace_file.include?("_rwebspec.rb") || trace_file.include?("_test.rb") || trace_file.include?("_cmd.rb"))
|
56
|
+
if !trace_lines.empty?
|
57
|
+
connect_to_testwise(" TRACE", trace_lines.reverse.join("|"))
|
58
|
+
end
|
59
|
+
|
60
|
+
rescue => e
|
61
|
+
puts "failed to capture log: #{e}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def connect_to_testwise (message_type, body)
|
67
|
+
begin
|
68
|
+
the_message = message_type + "|" + body
|
69
|
+
if @last_message == the_message then # ignore the message same as preivous one
|
70
|
+
return
|
71
|
+
end
|
72
|
+
itest_port = $ITEST2_TRACE_PORT || 7025
|
73
|
+
itest_socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
74
|
+
itest_socket.connect(Socket.pack_sockaddr_in(itest_port, '127.0.0.1'))
|
75
|
+
itest_socket.puts(the_message)
|
76
|
+
@last_message = the_message
|
77
|
+
itest_socket.close
|
78
|
+
rescue => e
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RWebSpec
|
2
|
+
module UsingPages
|
3
|
+
|
4
|
+
# support Ruby 1.9
|
5
|
+
def self.extended(kclass)
|
6
|
+
caller_file = caller[1]
|
7
|
+
if caller_file && caller_file =~ /^(.*):\d+.*$/
|
8
|
+
file = $1
|
9
|
+
dir = File.expand_path(File.dirname(file))
|
10
|
+
kclass.const_set "TestFileDir", dir
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Example
|
15
|
+
# pages :all
|
16
|
+
# pages :login_page, :payment_page
|
17
|
+
# pages :login_page, :payment_page, :page_dir => "c:/tmp"
|
18
|
+
def pages(*args)
|
19
|
+
return if args.nil? or args.empty?
|
20
|
+
|
21
|
+
test_file_dir = class_eval{ self::TestFileDir }
|
22
|
+
default_page_dir = File.join(test_file_dir, "pages")
|
23
|
+
#puts "debug: default_page_dir :#{default_page_dir}}"
|
24
|
+
page_dir = default_page_dir
|
25
|
+
|
26
|
+
page_files = []
|
27
|
+
args.each do |x|
|
28
|
+
if x.class == Hash && x[:page_dir]
|
29
|
+
page_dir = x[:page_dir]
|
30
|
+
else
|
31
|
+
page_files << x
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
if page_files.size == 1 && page_files[0] == :all
|
36
|
+
Dir[File.expand_path(page_dir)+ "/*_page.rb"].each { |page_file|
|
37
|
+
load page_file
|
38
|
+
}
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
42
|
+
page_files.each do |page|
|
43
|
+
page_file = File.join(page_dir, page.to_s)
|
44
|
+
load page_file
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,742 @@
|
|
1
|
+
#***********************************************************
|
2
|
+
#* Copyright (c) 2006, Zhimin Zhan.
|
3
|
+
#* Distributed open-source, see full license in MIT-LICENSE
|
4
|
+
#***********************************************************
|
5
|
+
|
6
|
+
begin
|
7
|
+
require "selenium-webdriver"
|
8
|
+
rescue LoadError => e
|
9
|
+
raise "You have must at least WebDriver installed"
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'sanitize'
|
13
|
+
require File.join(File.dirname(__FILE__), "element_locator.rb")
|
14
|
+
|
15
|
+
module RWebSpec
|
16
|
+
|
17
|
+
class WebBrowser
|
18
|
+
|
19
|
+
include ElementLocator
|
20
|
+
|
21
|
+
attr_accessor :context
|
22
|
+
|
23
|
+
def initialize(base_url = nil, existing_browser = nil, options = {})
|
24
|
+
default_options = {:speed => "zippy",
|
25
|
+
:visible => true,
|
26
|
+
:highlight_colour => 'yellow',
|
27
|
+
:close_others => true
|
28
|
+
}
|
29
|
+
options = default_options.merge options
|
30
|
+
@context = Context.new base_url if base_url
|
31
|
+
|
32
|
+
case RUBY_PLATFORM
|
33
|
+
when /java/i
|
34
|
+
initialize_celerity_browser(base_url, options)
|
35
|
+
when /mswin|windows|mingw/i
|
36
|
+
options[:browser] ||= "ie"
|
37
|
+
case options[:browser].to_s
|
38
|
+
when "firefox"
|
39
|
+
initialize_firefox_browser(existing_browser, base_url, options)
|
40
|
+
when "chrome"
|
41
|
+
initialize_chrome_browser(existing_browser, base_url, options)
|
42
|
+
when "ie"
|
43
|
+
initialize_ie_browser(existing_browser, options)
|
44
|
+
end
|
45
|
+
|
46
|
+
else
|
47
|
+
puts "Ruby Linux or Mac platform: firefox"
|
48
|
+
options[:browser] ||= "firefox"
|
49
|
+
case options[:browser].to_s
|
50
|
+
when "firefox"
|
51
|
+
initialize_firefox_browser(existing_browser, base_url, options)
|
52
|
+
when "chrome"
|
53
|
+
initialize_chrome_browser(existing_browser, base_url, options)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize_firefox_browser(existing_browser, base_url, options)
|
59
|
+
if existing_browser then
|
60
|
+
@browser = existing_browser
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
64
|
+
@browser = Selenium::WebDriver.for :firefox
|
65
|
+
@browser.navigate.to base_url
|
66
|
+
end
|
67
|
+
|
68
|
+
def initialize_chrome_browser(existing_browser, base_url, options)
|
69
|
+
if existing_browser then
|
70
|
+
@browser = existing_browser
|
71
|
+
return
|
72
|
+
end
|
73
|
+
|
74
|
+
@browser = Selenium::WebDriver.for :chrome
|
75
|
+
@browser.navigate.to base_url
|
76
|
+
end
|
77
|
+
|
78
|
+
def initialize_htmlunit_browser(base_url, options)
|
79
|
+
# default_celerity_options = {:proxy => nil, :browser => :firefox, :resynchronize => true, :log_level => :off}
|
80
|
+
# options = default_celerity_options.merge options
|
81
|
+
# options.each { |k, v| options.delete(k) unless default_celerity_options.keys.include?(k) }
|
82
|
+
@browser = Selenium::WebDriver.for :htmlunit
|
83
|
+
@browser.navigate.to base_url
|
84
|
+
end
|
85
|
+
|
86
|
+
def initialize_ie_browser(existing_browser, options)
|
87
|
+
if existing_browser then
|
88
|
+
@browser = existing_browser
|
89
|
+
if $ITEST2_EMULATE_TYPING && $ITEST2_TYPING_SPEED then
|
90
|
+
@browser.set_slow_speed if $ITEST2_TYPING_SPEED == 'slow'
|
91
|
+
@browser.set_fast_speed if $ITEST2_TYPING_SPEED == 'fast'
|
92
|
+
else
|
93
|
+
@browser.speed = :zippy
|
94
|
+
end
|
95
|
+
return
|
96
|
+
end
|
97
|
+
|
98
|
+
@browser = Selenium::WebDriver.for :ie
|
99
|
+
# if $ITEST2_EMULATE_TYPING && $ITEST2_TYPING_SPEED then
|
100
|
+
# @browser.set_slow_speed if $ITEST2_TYPING_SPEED == 'slow'
|
101
|
+
# @browser.set_fast_speed if $ITEST2_TYPING_SPEED == 'fast'
|
102
|
+
# else
|
103
|
+
# @browser.speed = :zippy
|
104
|
+
# end
|
105
|
+
# @browser.activeObjectHighLightColor = options[:highlight_colour]
|
106
|
+
# @browser.visible = options[:visible] unless $HIDE_IE
|
107
|
+
# #NOTE: close_others fails
|
108
|
+
# if RUBY_VERSION =~ /^1\.8/ && options[:close_others] then
|
109
|
+
# @browser.close_others
|
110
|
+
# else
|
111
|
+
# puts "close other browser instances not working yet in Ruby 1.9.1 version of Watir"
|
112
|
+
# end
|
113
|
+
end
|
114
|
+
|
115
|
+
# TODO resuse not working yet
|
116
|
+
def self.reuse(base_url, options)
|
117
|
+
if self.is_windows? && $ITEST2_BROWSER != "Firefox"
|
118
|
+
Watir::IE.each do |browser_window|
|
119
|
+
return WebBrowser.new(base_url, browser_window, options)
|
120
|
+
end
|
121
|
+
#puts "no browser instance found"
|
122
|
+
WebBrowser.new(base_url, nil, options)
|
123
|
+
else
|
124
|
+
WebBrowser.new(base_url, nil, options)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# for popup windows
|
129
|
+
def self.new_from_existing(underlying_browser, web_context = nil)
|
130
|
+
return WebBrowser.new(web_context ? web_context.base_url : nil, underlying_browser, {:close_others => false})
|
131
|
+
end
|
132
|
+
|
133
|
+
def find_element(* args)
|
134
|
+
@browser.send("find_element", *args)
|
135
|
+
end
|
136
|
+
|
137
|
+
def find_elements(* args)
|
138
|
+
@browser.send("find_elements", *args)
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Delegate to WebDriver
|
143
|
+
#
|
144
|
+
[: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
|
+
tag_name = method
|
146
|
+
define_method method do |* args|
|
147
|
+
if args.size == 2 then
|
148
|
+
find_element(args[0].to_sym, args[1])
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
alias td cell
|
153
|
+
alias check_box checkbox # seems watir doc is wrong, checkbox not check_box
|
154
|
+
alias tr row
|
155
|
+
|
156
|
+
# Wrapp of Watir's area to support Firefox and Watir
|
157
|
+
#
|
158
|
+
# Note: FireWatir does not support area directly, treat it as text_field
|
159
|
+
def area(* args)
|
160
|
+
if is_firefox?
|
161
|
+
text_field(* args)
|
162
|
+
else
|
163
|
+
@browser.send("area", * args)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def modal_dialog(how=nil, what=nil)
|
168
|
+
@browser.modal_dialog(how, what)
|
169
|
+
end
|
170
|
+
|
171
|
+
# This is the main method for accessing a generic element with a given attibute
|
172
|
+
# * how - symbol - how we access the element. Supports all values except :index and :xpath
|
173
|
+
# * what - string, integer or regular expression - what we are looking for,
|
174
|
+
#
|
175
|
+
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
176
|
+
#
|
177
|
+
# returns an Watir::Element object
|
178
|
+
#
|
179
|
+
# Typical Usage
|
180
|
+
#
|
181
|
+
# element(:class, /foo/) # access the first element with class 'foo'. We can use a string in place of the regular expression
|
182
|
+
# element(:id, "11") # access the first element that matches an id
|
183
|
+
def element(how, what)
|
184
|
+
return @browser.element(how, what)
|
185
|
+
end
|
186
|
+
|
187
|
+
# this is the main method for accessing generic html elements by an attribute
|
188
|
+
#
|
189
|
+
# Returns a HTMLElements object
|
190
|
+
#
|
191
|
+
# Typical usage:
|
192
|
+
#
|
193
|
+
# elements(:class, 'test').each { |l| puts l.to_s } # iterate through all elements of a given attribute
|
194
|
+
# elements(:alt, 'foo')[1].to_s # get the first element of a given attribute
|
195
|
+
# elements(:id, 'foo').length # show how many elements are foung in the collection
|
196
|
+
#
|
197
|
+
def elements(how, what)
|
198
|
+
return @browser.elements(how, what)
|
199
|
+
end
|
200
|
+
|
201
|
+
def show_all_objects
|
202
|
+
@browser.show_all_objects
|
203
|
+
end
|
204
|
+
|
205
|
+
# Returns the specified ole object for input elements on a web page.
|
206
|
+
#
|
207
|
+
# This method is used internally by Watir and should not be used externally. It cannot be marked as private because of the way mixins and inheritance work in watir
|
208
|
+
#
|
209
|
+
# * how - symbol - the way we look for the object. Supported values are
|
210
|
+
# - :name
|
211
|
+
# - :id
|
212
|
+
# - :index
|
213
|
+
# - :value etc
|
214
|
+
# * what - string that we are looking for, ex. the name, or id tag attribute or index of the object we are looking for.
|
215
|
+
# * types - what object types we will look at.
|
216
|
+
# * value - used for objects that have one name, but many values. ex. radio lists and checkboxes
|
217
|
+
def locate_input_element(how, what, types, value=nil)
|
218
|
+
@browser.locate_input_element(how, what, types, value)
|
219
|
+
end
|
220
|
+
|
221
|
+
# This is the main method for accessing map tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/map.asp?frame=true
|
222
|
+
# * how - symbol - how we access the map,
|
223
|
+
# * what - string, integer or regular expression - what we are looking for,
|
224
|
+
#
|
225
|
+
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
226
|
+
#
|
227
|
+
# returns a map object
|
228
|
+
#
|
229
|
+
# Typical Usage
|
230
|
+
#
|
231
|
+
# map(:id, /list/) # access the first map that matches list.
|
232
|
+
# map(:index,2) # access the second map on the page
|
233
|
+
# map(:title, "A Picture") # access a map using the tooltip text. See http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/title_1.asp?frame=true
|
234
|
+
#
|
235
|
+
def map(how, what=nil)
|
236
|
+
@browser.map(how, what)
|
237
|
+
end
|
238
|
+
|
239
|
+
def contains_text(text)
|
240
|
+
@browser.contains_text(text);
|
241
|
+
end
|
242
|
+
|
243
|
+
# return HTML of current web page
|
244
|
+
def page_source
|
245
|
+
@browser.page_source
|
246
|
+
end
|
247
|
+
alias html_body page_source
|
248
|
+
alias html page_source
|
249
|
+
|
250
|
+
def page_title
|
251
|
+
@browser.title
|
252
|
+
end
|
253
|
+
|
254
|
+
#TODO return plain text of current web page
|
255
|
+
def text
|
256
|
+
Sanitize.clean(html)
|
257
|
+
# @browser.text
|
258
|
+
end
|
259
|
+
|
260
|
+
[:images, :links, :buttons, :select_lists, :checkboxes, :radios, :text_fields, :divs, :dls, :dds, :dts, :ems, :lis, :maps, :spans, :strongs, :ps, :pres, :labels].each do |method|
|
261
|
+
define_method method do
|
262
|
+
@browser.send(method)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# current url
|
267
|
+
def current_url
|
268
|
+
@browser.current_url
|
269
|
+
end
|
270
|
+
alias url current_url
|
271
|
+
|
272
|
+
def base_url=(new_base_url)
|
273
|
+
if @context
|
274
|
+
@conext.base_url = new_base_url
|
275
|
+
return
|
276
|
+
end
|
277
|
+
@context = Context.new base_url
|
278
|
+
end
|
279
|
+
|
280
|
+
def underlying_browser
|
281
|
+
@browser
|
282
|
+
end
|
283
|
+
|
284
|
+
def is_ie?
|
285
|
+
puts @browser.browser.to_s
|
286
|
+
@browser.browser.to_s == "ie"
|
287
|
+
end
|
288
|
+
|
289
|
+
def is_firefox?
|
290
|
+
@browser.browser.to_s == "firefox"
|
291
|
+
end
|
292
|
+
|
293
|
+
# Close the browser window. Useful for automated test suites to reduce
|
294
|
+
# test interaction.
|
295
|
+
def close_browser
|
296
|
+
@browser.quit
|
297
|
+
sleep 1
|
298
|
+
end
|
299
|
+
alias close close_browser
|
300
|
+
|
301
|
+
#TODO determine browser type, check FireWatir support or not
|
302
|
+
def self.close_all_browsers
|
303
|
+
if RUBY_PLATFORM.downcase.include?("mswin")
|
304
|
+
Watir::IE.close_all
|
305
|
+
else
|
306
|
+
# raise "not supported in FireFox yet."
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def full_url(relative_url)
|
311
|
+
if @context && @context.base_url
|
312
|
+
@context.base_url + relative_url
|
313
|
+
else
|
314
|
+
relative_url
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
# Crahses where http:///ssshtttp:///
|
319
|
+
def begin_at(relative_url)
|
320
|
+
if relative_url =~ /\s*^http/
|
321
|
+
@browser.navigate.to relative_url
|
322
|
+
else
|
323
|
+
@browser.navigate.to full_url(relative_url)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
def browser_opened?
|
328
|
+
begin
|
329
|
+
@browser != nil
|
330
|
+
rescue => e
|
331
|
+
return false
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
# Some browsers (i.e. IE) need to be waited on before more actions can be
|
336
|
+
# performed. Most action methods in Watir::Simple already call this before
|
337
|
+
# and after.
|
338
|
+
def wait_for_browser
|
339
|
+
# NOTE: no need any more
|
340
|
+
end
|
341
|
+
|
342
|
+
|
343
|
+
# A convenience method to wait at both ends of an operation for the browser
|
344
|
+
# to catch up.
|
345
|
+
def wait_before_and_after
|
346
|
+
wait_for_browser
|
347
|
+
yield
|
348
|
+
wait_for_browser
|
349
|
+
end
|
350
|
+
|
351
|
+
|
352
|
+
[:focus, :close_others].each do |method|
|
353
|
+
define_method(method) do
|
354
|
+
@browser.send(method)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def forward
|
359
|
+
@browser.navigate().forward
|
360
|
+
end
|
361
|
+
alias go_forward forward
|
362
|
+
|
363
|
+
# TODO can't browse back if on invalid page
|
364
|
+
def back
|
365
|
+
@browser.navigate.back
|
366
|
+
end
|
367
|
+
alias go_back back
|
368
|
+
|
369
|
+
def refresh
|
370
|
+
@browser.navigate().refresh
|
371
|
+
end
|
372
|
+
alias refresh_page refresh
|
373
|
+
|
374
|
+
# Go to a page
|
375
|
+
# Usage:
|
376
|
+
# open_browser("http://www.itest2.com"
|
377
|
+
# ....
|
378
|
+
# goto_page("/purchase") # full url => http://www.itest.com/purchase
|
379
|
+
def goto_page(page)
|
380
|
+
goto_url full_url(page);
|
381
|
+
end
|
382
|
+
|
383
|
+
# Go to a URL directly
|
384
|
+
# goto_url("http://www.itest2.com/downloads")
|
385
|
+
def goto_url(url)
|
386
|
+
@browser.navigate.to url
|
387
|
+
end
|
388
|
+
|
389
|
+
# text fields
|
390
|
+
def enter_text_into_field_with_name(name, text)
|
391
|
+
the_element = find_element(:name, name)
|
392
|
+
if the_element.tag_name == "input" || the_element.tag_name == "textarea" then
|
393
|
+
the_element.clear
|
394
|
+
the_element.send_keys(text)
|
395
|
+
else
|
396
|
+
elements = find_elements(:name, name)
|
397
|
+
if elements.size == 1 then
|
398
|
+
elements[0].send_keys(text)
|
399
|
+
else
|
400
|
+
element_set = elements.select {|x| x.tag_name == "textarea" || (x.tag_name == "input" && x.attribute("text")) }
|
401
|
+
element_set[0].send_keys(text)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
return true
|
405
|
+
end
|
406
|
+
|
407
|
+
alias set_form_element enter_text_into_field_with_name
|
408
|
+
alias enter_text enter_text_into_field_with_name
|
409
|
+
alias set_hidden_field set_form_element
|
410
|
+
|
411
|
+
#links
|
412
|
+
def click_link_with_id(link_id, opts = {})
|
413
|
+
if opts && opts[:index]
|
414
|
+
elements = find_elements(:id, link_id)
|
415
|
+
elements[opts[:index]-1].click
|
416
|
+
else
|
417
|
+
find_element(:id, link_id).click
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
##
|
422
|
+
# click_link_with_text("Login")
|
423
|
+
# click_link_with_text("Show", :index => 2)
|
424
|
+
def click_link_with_text(link_text, opts = {})
|
425
|
+
if opts && opts[:index]
|
426
|
+
elements = find_elements(:link_text, link_text)
|
427
|
+
elements[opts[:index]-1].click
|
428
|
+
else
|
429
|
+
find_element(:link_text, link_text).click
|
430
|
+
end
|
431
|
+
end
|
432
|
+
alias click_link click_link_with_text
|
433
|
+
|
434
|
+
|
435
|
+
# Click a button with give HTML id
|
436
|
+
# Usage:
|
437
|
+
# click_button_with_id("btn_sumbit")
|
438
|
+
def click_button_with_id(id, opts = {})
|
439
|
+
find_element(:id, id).click
|
440
|
+
end
|
441
|
+
|
442
|
+
# Click a button with give name
|
443
|
+
# Usage:
|
444
|
+
# click_button_with_name("confirm")
|
445
|
+
# click_button_with_name("confirm", :index => 2)
|
446
|
+
def click_button_with_name(name, opts={})
|
447
|
+
find_element(:name, name).click
|
448
|
+
end
|
449
|
+
|
450
|
+
# Click a button with caption
|
451
|
+
#
|
452
|
+
# TODO: Caption is same as value
|
453
|
+
#
|
454
|
+
# Usage:
|
455
|
+
# click_button_with_caption("Confirm payment")
|
456
|
+
def click_button_with_caption(caption, opts={})
|
457
|
+
all_buttons = button_elements
|
458
|
+
matching_buttons = all_buttons.select{|x| x.attribute('value') == caption}
|
459
|
+
if matching_buttons.size > 0
|
460
|
+
|
461
|
+
if opts && opts[:index]
|
462
|
+
puts "Call matching buttons: #{matching_buttons.inspect}"
|
463
|
+
first_match = matching_buttons[opts[:index].to_i() - 1]
|
464
|
+
first_match.click
|
465
|
+
end
|
466
|
+
|
467
|
+
the_button = matching_buttons[0]
|
468
|
+
the_button.click
|
469
|
+
|
470
|
+
else
|
471
|
+
raise "No button with value: #{caption} found"
|
472
|
+
end
|
473
|
+
end
|
474
|
+
alias click_button click_button_with_caption
|
475
|
+
alias click_button_with_text click_button_with_caption
|
476
|
+
|
477
|
+
|
478
|
+
# click_button_with_caption("Confirm payment")
|
479
|
+
def click_button_with_value(value, opts={})
|
480
|
+
all_buttons = button_elements
|
481
|
+
if opts && opts[:index]
|
482
|
+
all_buttons.select{|x| x.attribute('value') == caption}[index]
|
483
|
+
else
|
484
|
+
all_buttons.each do |button|
|
485
|
+
if button.attribute('value') == value then
|
486
|
+
button.click
|
487
|
+
return
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
# Click image buttion with image source name
|
494
|
+
#
|
495
|
+
# For an image submit button <input name="submit" type="image" src="/images/search_button.gif">
|
496
|
+
# click_button_with_image("search_button.gif")
|
497
|
+
def click_button_with_image_src_contains(image_filename)
|
498
|
+
all_buttons = button_elements
|
499
|
+
found = nil
|
500
|
+
all_buttons.select do |x|
|
501
|
+
if x["src"] =~ /#{Regexp.escape(image_filename)}/
|
502
|
+
found = x
|
503
|
+
break
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
raise "not image button with src: #{image_filename} found" if found.nil?
|
508
|
+
found.click
|
509
|
+
end
|
510
|
+
|
511
|
+
alias click_button_with_image click_button_with_image_src_contains
|
512
|
+
# Select a dropdown list by name
|
513
|
+
# Usage:
|
514
|
+
# select_option("country", "Australia")
|
515
|
+
def select_option(selectName, text)
|
516
|
+
select_box = find_element(:name, selectName)
|
517
|
+
|
518
|
+
options = select_box.find_elements(:tag_name, "option")
|
519
|
+
options.each do |opt|
|
520
|
+
# puts opt.methods
|
521
|
+
opt.click if text == opt.text
|
522
|
+
end
|
523
|
+
# select_list(:name, selectName).select(option)
|
524
|
+
end
|
525
|
+
|
526
|
+
# submit first submit button
|
527
|
+
def submit(buttonName = nil)
|
528
|
+
if (buttonName.nil?) then
|
529
|
+
buttons.each { |button|
|
530
|
+
next if button.type != 'submit'
|
531
|
+
button.click
|
532
|
+
return
|
533
|
+
}
|
534
|
+
else
|
535
|
+
click_button_with_name(buttonName)
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
# Check a checkbox
|
540
|
+
# Usage:
|
541
|
+
# check_checkbox("agree")
|
542
|
+
# check_checkbox("agree", "true")
|
543
|
+
def check_checkbox(checkBoxName, values=nil)
|
544
|
+
if values
|
545
|
+
values.class == Array ? arys = values : arys = [values]
|
546
|
+
elements = find_elements(:name, checkBoxName)
|
547
|
+
the_checkbox = elements[0] if elements.size == 1
|
548
|
+
if the_checkbox
|
549
|
+
the_checkbox.click unless the_checkbox.selected?
|
550
|
+
return
|
551
|
+
end
|
552
|
+
|
553
|
+
arys.each { |cbx_value|
|
554
|
+
elements.each do |elem|
|
555
|
+
elem.click if elem.attribute('value') == cbx_value && !the_checkbox.selected?
|
556
|
+
end
|
557
|
+
}
|
558
|
+
else
|
559
|
+
the_checkbox = find_element(:name, checkBoxName)
|
560
|
+
the_checkbox.click unless the_checkbox.selected?
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
# Check a checkbox
|
565
|
+
# Usage:
|
566
|
+
# uncheck_checkbox("agree")
|
567
|
+
# uncheck_checkbox("agree", "false")
|
568
|
+
def uncheck_checkbox(checkBoxName, values = nil)
|
569
|
+
if values
|
570
|
+
values.class == Array ? arys = values : arys = [values]
|
571
|
+
elements = find_elements(:name, checkBoxName)
|
572
|
+
the_checkbox = elements[0] if elements.size == 1
|
573
|
+
if the_checkbox
|
574
|
+
the_checkbox.click if the_checkbox.selected?
|
575
|
+
return
|
576
|
+
end
|
577
|
+
|
578
|
+
arys.each { |cbx_value|
|
579
|
+
elements.each do |elem|
|
580
|
+
elem.click if elem.attribute('value') == cbx_value && the_checkbox && the_checkbox.selected?
|
581
|
+
end
|
582
|
+
}
|
583
|
+
else
|
584
|
+
the_checkbox = find_element(:name, checkBoxName)
|
585
|
+
the_checkbox.click if the_checkbox.selected?
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
|
590
|
+
# Click a radio button
|
591
|
+
# Usage:
|
592
|
+
# click_radio_option("country", "Australia")
|
593
|
+
def click_radio_option(radio_group, radio_option)
|
594
|
+
the_radio_button = find_element(:xpath, "//input[@type='radio' and @name='#{radio_group}' and @value='#{radio_option}']")
|
595
|
+
the_radio_button.click
|
596
|
+
end
|
597
|
+
alias click_radio_button click_radio_option
|
598
|
+
|
599
|
+
# Clear a radio button
|
600
|
+
# Usage:
|
601
|
+
# click_radio_option("country", "Australia")
|
602
|
+
def clear_radio_option(radio_group, radio_option)
|
603
|
+
the_radio_button = find_element(:xpath, "//input[@type='radio' and @name='#{radio_group}' and @value='#{radio_option}']")
|
604
|
+
the_radio_button.clear
|
605
|
+
end
|
606
|
+
alias clear_radio_button clear_radio_option
|
607
|
+
|
608
|
+
def element_by_id(elem_id)
|
609
|
+
@browser.find_element(:id, elem_id)
|
610
|
+
end
|
611
|
+
|
612
|
+
def element_value(elementId)
|
613
|
+
find_element(:id, elementId).attribute('value')
|
614
|
+
end
|
615
|
+
|
616
|
+
def element_source(elementId)
|
617
|
+
elem = element_by_id(elementId)
|
618
|
+
assert_not_nil(elem, "HTML element: #{elementId} not exists")
|
619
|
+
elem.innerHTML
|
620
|
+
end
|
621
|
+
|
622
|
+
def select_file_for_upload(file_field, file_path)
|
623
|
+
is_on_windows = RUBY_PLATFORM.downcase.include?("mingw") || RUBY_PLATFORM.downcase.include?("mswin")
|
624
|
+
normalized_file_path = is_on_windows ? file_path.gsub("/", "\\") : file_path
|
625
|
+
file_field(:name, file_field).set(normalized_file_path)
|
626
|
+
end
|
627
|
+
|
628
|
+
def start_window(url = nil)
|
629
|
+
@browser.start_window(url);
|
630
|
+
end
|
631
|
+
|
632
|
+
# Attach to existing browser
|
633
|
+
#
|
634
|
+
# Usage:
|
635
|
+
# WebBrowser.attach_browser(:title, "iTest2")
|
636
|
+
# WebBrowser.attach_browser(:url, "http://www.itest2.com")
|
637
|
+
# WebBrowser.attach_browser(:url, "http://www.itest2.com", {:browser => "Firefox", :base_url => "http://www.itest2.com"})
|
638
|
+
# WebBrowser.attach_browser(:title, /agileway\.com\.au\/attachment/) # regular expression
|
639
|
+
def self.attach_browser(how, what, options={})
|
640
|
+
default_options = {:browser => "IE"}
|
641
|
+
options = default_options.merge(options)
|
642
|
+
site_context = Context.new(options[:base_url]) if options[:base_url]
|
643
|
+
if (options[:browser].to_s == "firefox")
|
644
|
+
ff = FireWatir::Firefox.attach(how, what)
|
645
|
+
return WebBrowser.new_from_existing(ff, site_context)
|
646
|
+
else
|
647
|
+
return WebBrowser.new_from_existing(Watir::IE.attach(how, what), site_context)
|
648
|
+
end
|
649
|
+
end
|
650
|
+
|
651
|
+
# Attach a Watir::IE instance to a popup window.
|
652
|
+
#
|
653
|
+
# Typical usage
|
654
|
+
# new_popup_window(:url => "http://www.google.com/a.pdf")
|
655
|
+
def new_popup_window(options, browser = "ie")
|
656
|
+
if is_firefox?
|
657
|
+
raise "not implemented"
|
658
|
+
else
|
659
|
+
if options[:url]
|
660
|
+
Watir::IE.attach(:url, options[:url])
|
661
|
+
elsif options[:title]
|
662
|
+
Watir::IE.attach(:title, options[:title])
|
663
|
+
else
|
664
|
+
raise 'Please specify title or url of new pop up window'
|
665
|
+
end
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
# ---
|
670
|
+
# For deubgging
|
671
|
+
# ---
|
672
|
+
def dump_response(stream = nil)
|
673
|
+
stream.nil? ? puts(page_source) : stream.puts(page_source)
|
674
|
+
end
|
675
|
+
|
676
|
+
# A Better Popup Handler using the latest Watir version. Posted by Mark_cain@rl.gov
|
677
|
+
#
|
678
|
+
# http://wiki.openqa.org/display/WTR/FAQ#FAQ-HowdoIattachtoapopupwindow%3F
|
679
|
+
#
|
680
|
+
def start_clicker(button, waitTime= 9, user_input=nil)
|
681
|
+
# get a handle if one exists
|
682
|
+
hwnd = @browser.enabled_popup(waitTime)
|
683
|
+
if (hwnd) # yes there is a popup
|
684
|
+
w = WinClicker.new
|
685
|
+
if (user_input)
|
686
|
+
w.setTextValueForFileNameField(hwnd, "#{user_input}")
|
687
|
+
end
|
688
|
+
# I put this in to see the text being input it is not necessary to work
|
689
|
+
sleep 3
|
690
|
+
# "OK" or whatever the name on the button is
|
691
|
+
w.clickWindowsButton_hwnd(hwnd, "#{button}")
|
692
|
+
#
|
693
|
+
# this is just cleanup
|
694
|
+
w = nil
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
# return underlying browser
|
699
|
+
def ie
|
700
|
+
@browser.class == "internet_explorer" ? @browser : nil;
|
701
|
+
end
|
702
|
+
|
703
|
+
# return underlying firefox browser object, raise error if not running using Firefox
|
704
|
+
def firefox
|
705
|
+
is_firefox? ? @browser : nil;
|
706
|
+
end
|
707
|
+
|
708
|
+
def htmlunit
|
709
|
+
raise "can't call this as it is configured to use Celerity" unless RUBY_PLATFORM =~ /java/
|
710
|
+
@browser
|
711
|
+
end
|
712
|
+
|
713
|
+
# Save current web page source to file
|
714
|
+
# usage:
|
715
|
+
# save_page("/tmp/01.html")
|
716
|
+
# save_page() => # will save to "20090830112200.html"
|
717
|
+
def save_page(file_name = nil)
|
718
|
+
file_name ||= Time.now.strftime("%Y%m%d%H%M%S") + ".html"
|
719
|
+
puts "about to save page: #{File.expand_path(file_name)}" if $DEBUG
|
720
|
+
File.open(file_name, "w").puts page_source
|
721
|
+
end
|
722
|
+
|
723
|
+
|
724
|
+
# Verify the next page following an operation.
|
725
|
+
#
|
726
|
+
# Typical usage:
|
727
|
+
# browser.expect_page HomePage
|
728
|
+
def expect_page(page_clazz, argument = nil)
|
729
|
+
if argument
|
730
|
+
page_clazz.new(self, argument)
|
731
|
+
else
|
732
|
+
page_clazz.new(self)
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
736
|
+
# is it running in MS Windows platforms?
|
737
|
+
def self.is_windows?
|
738
|
+
RUBY_PLATFORM.downcase.include?("mswin") or RUBY_PLATFORM.downcase.include?("mingw")
|
739
|
+
end
|
740
|
+
|
741
|
+
end
|
742
|
+
end
|