rwebspec-webdriver 0.1
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 +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,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
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#***********************************************************
|
2
|
+
#* Copyright (c) 2006 - 2009 Zhimin Zhan.
|
3
|
+
#* Distributed open-source, see full license in MIT-LICENSE
|
4
|
+
#***********************************************************
|
5
|
+
|
6
|
+
module RWebSpec
|
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
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'active_record' # change rwebspec/database
|
2
|
+
|
3
|
+
module RWebSpec
|
4
|
+
module DatabaseChecker
|
5
|
+
|
6
|
+
# Example
|
7
|
+
# connect_to_database mysql_db(:host => "localhost", :database => "lavabuild_local", :user => "root", :password => ""), true
|
8
|
+
def mysql_db(settings)
|
9
|
+
options = {:adapter => "mysql"}
|
10
|
+
options.merge!(settings)
|
11
|
+
end
|
12
|
+
|
13
|
+
# connect_to_database sqlite3_db(:database => File.join(File.dirname(__FILE__), "testdata", "sample.sqlite3")), true
|
14
|
+
def sqlite3_db(settings)
|
15
|
+
options = {:adapter => "sqlite3"}
|
16
|
+
options.merge!(settings)
|
17
|
+
end
|
18
|
+
|
19
|
+
def sqlserver_db(settings)
|
20
|
+
options = {:adapter => "sqlserver"}
|
21
|
+
options[:username] ||= settings[:user]
|
22
|
+
options.merge!(settings)
|
23
|
+
end
|
24
|
+
|
25
|
+
def sqlserver_db_dbi(options)
|
26
|
+
options[:user] ||= options[:username]
|
27
|
+
options[:username] ||= options[:user]
|
28
|
+
conn_str = "DBI:ADO:Provider=SQLOLEDB;Data Source=#{options[:host]};Initial Catalog=#{options[:database]};User ID=\"#{options[:user]}\";password=\"#{options[:password]}\" "
|
29
|
+
dbh = DBI.connect(conn_str)
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear_database_connection
|
33
|
+
begin
|
34
|
+
ActiveRecord::Base.remove_connection
|
35
|
+
rescue => e
|
36
|
+
puts "failed o clear database connection: #{e}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Connect to databse, example
|
41
|
+
# mysql_db(:host => "localhost", :database => "lavabuild_local", :user => "root", :password => "")
|
42
|
+
def connect_to_database(db_settings, force = false)
|
43
|
+
# only setup database connection once
|
44
|
+
if force
|
45
|
+
ActiveRecord::Base.establish_connection(db_settings)
|
46
|
+
else
|
47
|
+
begin
|
48
|
+
ActiveRecord::Base.connection
|
49
|
+
rescue => e
|
50
|
+
require 'pp'
|
51
|
+
pp db_settings
|
52
|
+
puts "failed to connect: #{e}"
|
53
|
+
ActiveRecord::Base.establish_connection(db_settings)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def load_table(table_name)
|
59
|
+
begin
|
60
|
+
ActiveRecord::Base.connection
|
61
|
+
rescue =>e
|
62
|
+
raise "No database connection setup yet, use connect_to_database() method"
|
63
|
+
end
|
64
|
+
class_name = table_name.classify
|
65
|
+
# define the class, so can use ActiveRecord in
|
66
|
+
# such as
|
67
|
+
# Perosn.count.should == 2
|
68
|
+
def_class = "class ::#{class_name} < ActiveRecord::Base; end"
|
69
|
+
eval def_class
|
70
|
+
return def_class
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,1009 @@
|
|
1
|
+
# convenient methods to drive the browser.
|
2
|
+
# convenient methods to drive the browser.
|
3
|
+
#
|
4
|
+
# Instead of
|
5
|
+
# browser.click_button("submit")
|
6
|
+
# You can just use
|
7
|
+
# click_button("submit")
|
8
|
+
#
|
9
|
+
require File.join(File.dirname(__FILE__), 'testwise_plugin')
|
10
|
+
require File.join(File.dirname(__FILE__), 'popup')
|
11
|
+
require File.join(File.dirname(__FILE__), 'matchers', "contains_text.rb")
|
12
|
+
|
13
|
+
require 'timeout'
|
14
|
+
require 'uri'
|
15
|
+
|
16
|
+
module RWebSpec
|
17
|
+
module Driver
|
18
|
+
include RWebSpec::TestWisePlugin
|
19
|
+
include RWebSpec::Popup
|
20
|
+
|
21
|
+
@@default_polling_interval = 1 # second
|
22
|
+
@@default_timeout = 30 # seconds
|
23
|
+
|
24
|
+
# open a browser, and set base_url via hash, but does not acually
|
25
|
+
#
|
26
|
+
# example:
|
27
|
+
# open_browser :base_url => http://localhost:8080
|
28
|
+
#
|
29
|
+
# There are 3 ways to set base url
|
30
|
+
# 1. pass as first argument
|
31
|
+
# 2. If running using TestWise, used as confiured
|
32
|
+
# 3. Use default value set
|
33
|
+
#
|
34
|
+
#
|
35
|
+
# New Options:
|
36
|
+
# :browser => :ie | :firefox | :chrome
|
37
|
+
def open_browser(base_url = nil, options = {})
|
38
|
+
puts "[DEBUG] [SeleniumDriver] Callling open_browser #{base_url}"
|
39
|
+
begin
|
40
|
+
support_unicode
|
41
|
+
rescue => e
|
42
|
+
puts "Unicode may not work in IE, #{e}"
|
43
|
+
end
|
44
|
+
|
45
|
+
base_url ||= $ITEST2_PROJECT_BASE_URL
|
46
|
+
base_url ||= $BASE_URL
|
47
|
+
raise "base_url must be set" if base_url.nil?
|
48
|
+
|
49
|
+
default_options = {:speed => "fast",
|
50
|
+
:visible => true,
|
51
|
+
:highlight_colour => 'yellow',
|
52
|
+
:close_others => true,
|
53
|
+
:start_new => true, # start a new browser always
|
54
|
+
:go => true}
|
55
|
+
|
56
|
+
options = default_options.merge options
|
57
|
+
|
58
|
+
if $ITEST2_BROWSER
|
59
|
+
options[:browser] = $ITEST2_BROWSER.downcase
|
60
|
+
end
|
61
|
+
if options[:firefox] && options[:browser].nil? then
|
62
|
+
options[:browser] = "firefox" # legacy
|
63
|
+
end
|
64
|
+
|
65
|
+
if base_url =~ /^file:/
|
66
|
+
uri_base = base_url
|
67
|
+
else
|
68
|
+
uri = URI.parse(base_url)
|
69
|
+
uri_base = "#{uri.scheme}://#{uri.host}:#{uri.port}"
|
70
|
+
end
|
71
|
+
|
72
|
+
if options[:start_new] || $celerity_loaded
|
73
|
+
puts "[DEBUG] [SeleniumBrowser] creating a new browser"
|
74
|
+
@web_browser = WebBrowser.new(uri_base, nil, options)
|
75
|
+
puts "[DEBUG] [SeleniumBrowser] browser: #{@web_browser.inspect}"
|
76
|
+
else
|
77
|
+
@web_browser = WebBrowser.reuse(uri_base, options) # Reuse existing browser
|
78
|
+
end
|
79
|
+
|
80
|
+
if base_url =~ /^file:/
|
81
|
+
goto_url(base_url) # for files, no base url
|
82
|
+
else
|
83
|
+
(uri.path.length == 0) ? begin_at(base_url) : begin_at(uri.path) if options[:go]
|
84
|
+
end
|
85
|
+
|
86
|
+
return @web_browser
|
87
|
+
end
|
88
|
+
|
89
|
+
alias open_browser_with open_browser
|
90
|
+
|
91
|
+
# return the underlying RWebSpec::Browser object
|
92
|
+
def browser
|
93
|
+
@web_browser
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def quit
|
98
|
+
@web_browser.quit
|
99
|
+
end
|
100
|
+
|
101
|
+
def find_element(how, what)
|
102
|
+
@web_browser.find_element(how, what)
|
103
|
+
end
|
104
|
+
|
105
|
+
def find_elements(how, what)
|
106
|
+
@web_browser.find_elements(how, what)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Close the current browser window (started by the script). If no browser started, then close
|
110
|
+
# all browser windows.
|
111
|
+
#
|
112
|
+
def close_browser
|
113
|
+
if @web_browser
|
114
|
+
# Old TestWise version
|
115
|
+
# @web_browser.close_browser unless $ITEST2_LEAVE_BROWSER_OPEN_AFTER_RUN
|
116
|
+
@web_browser.close_browser
|
117
|
+
else
|
118
|
+
WebBrowser.close_all_browsers
|
119
|
+
end
|
120
|
+
end
|
121
|
+
alias close_ie close_browser
|
122
|
+
|
123
|
+
|
124
|
+
# Close all opening browser windows
|
125
|
+
#
|
126
|
+
def close_all_browsers
|
127
|
+
#TODO
|
128
|
+
end
|
129
|
+
|
130
|
+
# Verify the next page following an operation.
|
131
|
+
#
|
132
|
+
# Typical usage:
|
133
|
+
# login_page.click_login
|
134
|
+
# expect_page HomePage
|
135
|
+
def expect_page(page_clazz, argument = nil)
|
136
|
+
if argument
|
137
|
+
@web_browser.expect_page(page_clazz, argument)
|
138
|
+
else
|
139
|
+
@web_browser.expect_page(page_clazz)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def context
|
144
|
+
@web_browser.context
|
145
|
+
end
|
146
|
+
|
147
|
+
# Starting browser with a URL
|
148
|
+
#
|
149
|
+
# Example:
|
150
|
+
# begin_at("http://www.itest2.com")
|
151
|
+
def begin_at(url)
|
152
|
+
puts "[DEBUG] [SeleniumBrowser] begin_at #{url}"
|
153
|
+
dump_caller_stack
|
154
|
+
@web_browser.begin_at(url)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Return the Watir::IE instance
|
158
|
+
#
|
159
|
+
def ie
|
160
|
+
@web_browser.ie
|
161
|
+
end
|
162
|
+
|
163
|
+
# Return the FireWatir::Firefox instance
|
164
|
+
#
|
165
|
+
def firefox
|
166
|
+
@web_browser.firefox
|
167
|
+
end
|
168
|
+
|
169
|
+
def is_firefox?
|
170
|
+
@web_browser.is_firefox? if @web_browser
|
171
|
+
end
|
172
|
+
|
173
|
+
def is_ie?
|
174
|
+
@web_browser.is_ie? if @web_browser
|
175
|
+
end
|
176
|
+
|
177
|
+
def is_htmlunit?
|
178
|
+
RUBY_PLATFORM =~ /java/ && @web_browser
|
179
|
+
end
|
180
|
+
|
181
|
+
# Go to another page on the testing site.
|
182
|
+
#
|
183
|
+
# open_browser("http://www.itest2.com")
|
184
|
+
# goto_page("/demo") # visit page http://www.itest2.com/demo
|
185
|
+
#
|
186
|
+
def goto_page(page)
|
187
|
+
perform_operation {
|
188
|
+
@web_browser.goto_page(page) if @web_browser
|
189
|
+
}
|
190
|
+
end
|
191
|
+
alias visit goto_page
|
192
|
+
|
193
|
+
# Go to another web site, normally different site being tested on
|
194
|
+
#
|
195
|
+
# open_browser("http://www.itest2.com")
|
196
|
+
# goto_url("http://myorganized.info")
|
197
|
+
def goto_url(url)
|
198
|
+
puts "Calling web_browser goto: #{@web_browser.inspect}"
|
199
|
+
@web_browser.goto_url url
|
200
|
+
end
|
201
|
+
|
202
|
+
# Attach to existinb browser window
|
203
|
+
#
|
204
|
+
# attach_browser(:title, )
|
205
|
+
def attach_browser(how, what, options = {})
|
206
|
+
#TODO
|
207
|
+
options.merge!(:browser => is_firefox? ? "Firefox" : "IE") unless options[:browser]
|
208
|
+
begin
|
209
|
+
options.merge!(:base_url => browser.context.base_url)
|
210
|
+
rescue => e
|
211
|
+
puts "failed to set base_url, ignore : #{e}"
|
212
|
+
end
|
213
|
+
WebBrowser.attach_browser(how, what, options)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Reuse current an opened browser window instead of opening a new one
|
217
|
+
# example:
|
218
|
+
# use_current_browser(:title, /.*/) # use what ever browser window
|
219
|
+
# use_current_browser(:title, "TestWise") # use browser window with title "TestWise"
|
220
|
+
def use_current_browser(how = :title, what = /.*/)
|
221
|
+
@web_browser = WebBrowser.attach_browser(how, what)
|
222
|
+
end
|
223
|
+
|
224
|
+
[:back, :forward, :refresh].each do |method|
|
225
|
+
define_method(method) do
|
226
|
+
perform_operation { @web_browser.send(method) if @web_browser }
|
227
|
+
end
|
228
|
+
end
|
229
|
+
alias refresh_page refresh
|
230
|
+
alias go_back back
|
231
|
+
alias go_forward forward
|
232
|
+
|
233
|
+
##
|
234
|
+
# Delegate to WebTester
|
235
|
+
#
|
236
|
+
# Note:
|
237
|
+
# label(:id, "abc") # OK
|
238
|
+
# label(:id, :abc) # Error
|
239
|
+
#
|
240
|
+
# Depends on which object type, you can use following attribute
|
241
|
+
# More details: http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
242
|
+
#
|
243
|
+
# :id Used to find an element that has an "id=" attribute. Since each id should be unique, according to the XHTML specification, this is recommended as the most reliable method to find an object. *
|
244
|
+
# :name Used to find an element that has a "name=" attribute. This is useful for older versions of HTML, but "name" is deprecated in XHTML. *
|
245
|
+
# :value Used to find a text field with a given default value, or a button with a given caption, or a text field
|
246
|
+
# :text Used for links, spans, divs and other element that contain text.
|
247
|
+
# :index Used to find the nth element of the specified type on a page. For example, button(:index, 2) finds the second button. Current versions of WATIR use 1-based indexing, but future versions will use 0-based indexing.
|
248
|
+
# :class Used for an element that has a "class=" attribute.
|
249
|
+
# :title Used for an element that has a "title=" attribute.
|
250
|
+
# :xpath Finds the item using xpath query.
|
251
|
+
# :method Used only for forms, the method attribute of a form is either GET or POST.
|
252
|
+
# :action Used only for form elements, specifies the URL where the form is to be submitted.
|
253
|
+
# :href Used to identify a link by its "href=" attribute.
|
254
|
+
# :src Used to identify an image by its URL.
|
255
|
+
#
|
256
|
+
|
257
|
+
# area <area> tags
|
258
|
+
# button <input> tags with type=button, submit, image or reset
|
259
|
+
# check_box <input> tags with type=checkbox
|
260
|
+
# div <div> tags
|
261
|
+
# form <form> tags
|
262
|
+
# frame frames, including both the <frame> elements and the corresponding pages
|
263
|
+
# h1 - h6 <h1>, <h2>, <h3>, <h4>, <h5>, <h6> tags
|
264
|
+
# hidden <input> tags with type=hidden
|
265
|
+
# image <img> tags
|
266
|
+
# label <label> tags (including "for" attribute)
|
267
|
+
# li <li> tags
|
268
|
+
# link <a> (anchor) tags
|
269
|
+
# map <map> tags
|
270
|
+
# radio <input> tags with the type=radio; known as radio buttons
|
271
|
+
# select_list <select> tags, known as drop-downs or drop-down lists
|
272
|
+
# span <span> tags
|
273
|
+
# table <table> tags, including row and cell methods for accessing nested elements
|
274
|
+
# text_field <input> tags with the type=text (single-line), type=textarea (multi-line), and type=password
|
275
|
+
# p <p> (paragraph) tags, because
|
276
|
+
[: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|
|
277
|
+
define_method method do |* args|
|
278
|
+
perform_operation { @web_browser.send(method, * args) if @web_browser }
|
279
|
+
end
|
280
|
+
end
|
281
|
+
alias td cell
|
282
|
+
alias check_box checkbox # seems watir doc is wrong, checkbox not check_box
|
283
|
+
alias tr row
|
284
|
+
|
285
|
+
|
286
|
+
[:images, :links, :buttons, :select_lists, :checkboxes, :radios, :text_fields].each do |method|
|
287
|
+
define_method method do
|
288
|
+
perform_operation { @web_browser.send(method) if @web_browser }
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# Check one or more checkboxes with same name, can accept a string or an array of string as values checkbox, pass array as values will try to set mulitple checkboxes.
|
293
|
+
#
|
294
|
+
# page.check_checkbox('bad_ones', 'Chicken Little')
|
295
|
+
# page.check_checkbox('good_ones', ['Cars', 'Toy Story'])
|
296
|
+
#
|
297
|
+
[:set_form_element, :click_link_with_text, :click_link_with_id, :submit, :click_button_with_id, :click_button_with_name, :click_button_with_caption, :click_button_with_value, :click_radio_option, :clear_radio_option, :check_checkbox, :uncheck_checkbox, :select_option].each do |method|
|
298
|
+
define_method method do |* args|
|
299
|
+
perform_operation { @web_browser.send(method, * args) if @web_browser }
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
alias enter_text set_form_element
|
304
|
+
alias set_hidden_field set_form_element
|
305
|
+
alias click_link click_link_with_text
|
306
|
+
alias click_button_with_text click_button_with_caption
|
307
|
+
alias click_button click_button_with_caption
|
308
|
+
alias click_radio_button click_radio_option
|
309
|
+
alias clear_radio_button clear_radio_option
|
310
|
+
|
311
|
+
# for text field can be easier to be identified by attribute "id" instead of "name", not recommended though
|
312
|
+
def enter_text_with_id(textfield_id, value)
|
313
|
+
perform_operation {
|
314
|
+
elements = find_elements(:id, textfield_id)
|
315
|
+
if elements.size == 1 then
|
316
|
+
elements[0].send_keys(value)
|
317
|
+
else
|
318
|
+
smaller_set = elements.select {|x| x.tag_name == "textarea" || (x.tag_name == "input" && x.attribute("text")) }
|
319
|
+
smaller_set[0].send_keys(value)
|
320
|
+
end
|
321
|
+
}
|
322
|
+
end
|
323
|
+
|
324
|
+
def perform_operation(& block)
|
325
|
+
begin
|
326
|
+
dump_caller_stack
|
327
|
+
operation_delay
|
328
|
+
yield
|
329
|
+
rescue RuntimeError => re
|
330
|
+
puts "[DEBUG] operation error: #{re}"
|
331
|
+
raise re
|
332
|
+
# ensure
|
333
|
+
# puts "[DEBUG] ensure #{perform_ok}" unless perform_ok
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def contains_text(text)
|
338
|
+
@web_browser.contains_text(text)
|
339
|
+
end
|
340
|
+
|
341
|
+
# In pages, can't use include, text.should include("abc") won't work
|
342
|
+
# Instead,
|
343
|
+
# text.should contains("abc"
|
344
|
+
def contains(str)
|
345
|
+
ContainsText.new(str)
|
346
|
+
end
|
347
|
+
|
348
|
+
alias contain contains
|
349
|
+
|
350
|
+
# Click image buttion with image source name
|
351
|
+
#
|
352
|
+
# For an image submit button <input name="submit" type="image" src="/images/search_button.gif">
|
353
|
+
# click_button_with_image("search_button.gif")
|
354
|
+
def click_button_with_image_src_contains(image_filename)
|
355
|
+
perform_operation {
|
356
|
+
@web_browser.click_button_with_image_src_contains(image_filename)
|
357
|
+
}
|
358
|
+
end
|
359
|
+
|
360
|
+
alias click_button_with_image click_button_with_image_src_contains
|
361
|
+
|
362
|
+
def new_popup_window(options)
|
363
|
+
@web_browser.new_popup_window(options)
|
364
|
+
end
|
365
|
+
|
366
|
+
|
367
|
+
# Warning: this does not work well with Firefox yet.
|
368
|
+
def element_text(elem_id)
|
369
|
+
@web_browser.element_value(elem_id)
|
370
|
+
end
|
371
|
+
|
372
|
+
# Identify DOM element by ID
|
373
|
+
# Warning: it is only supported on IE
|
374
|
+
def element_by_id(elem_id)
|
375
|
+
@web_browser.element_by_id(elem_id)
|
376
|
+
end
|
377
|
+
|
378
|
+
# ---
|
379
|
+
# For debugging
|
380
|
+
# ---
|
381
|
+
def dump_response(stream = nil)
|
382
|
+
@web_browser.dump_response(stream)
|
383
|
+
end
|
384
|
+
|
385
|
+
def default_dump_dir
|
386
|
+
if $ITEST2_RUNNING_SPEC_ID && $ITEST2_WORKING_DIR
|
387
|
+
|
388
|
+
$ITEST2_DUMP_DIR = File.join($ITEST2_WORKING_DIR, "dump")
|
389
|
+
FileUtils.mkdir($ITEST2_DUMP_DIR) unless File.exists?($ITEST2_DUMP_DIR)
|
390
|
+
|
391
|
+
spec_run_id = $ITEST2_RUNNING_SPEC_ID
|
392
|
+
spec_run_dir_name = spec_run_id.to_s.rjust(4, "0") unless spec_run_id == "unknown"
|
393
|
+
to_dir = File.join($ITEST2_DUMP_DIR, spec_run_dir_name)
|
394
|
+
else
|
395
|
+
to_dir = ENV['TEMP_DIR'] || (is_windows? ? "C:\\temp" : "/tmp")
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
# For current page souce to a file in specified folder for inspection
|
400
|
+
#
|
401
|
+
# save_current_page(:dir => "C:\\mysite", filename => "abc", :replacement => true)
|
402
|
+
def save_current_page(options = {})
|
403
|
+
default_options = {:replacement => true}
|
404
|
+
options = default_options.merge(options)
|
405
|
+
to_dir = options[:dir] || default_dump_dir
|
406
|
+
|
407
|
+
if options[:filename]
|
408
|
+
file_name = options[:filename]
|
409
|
+
else
|
410
|
+
file_name = Time.now.strftime("%m%d%H%M%S") + ".html"
|
411
|
+
end
|
412
|
+
|
413
|
+
Dir.mkdir(to_dir) unless File.exists?(to_dir)
|
414
|
+
file = File.join(to_dir, file_name)
|
415
|
+
|
416
|
+
content = page_source
|
417
|
+
base_url = @web_browser.context.base_url
|
418
|
+
current_url = @web_browser.url
|
419
|
+
current_url =~ /(.*\/).*$/
|
420
|
+
current_url_parent = $1
|
421
|
+
if options[:replacement] && base_url =~ /^http:/
|
422
|
+
File.new(file, "w").puts absolutize_page_hpricot(content, base_url, current_url_parent)
|
423
|
+
else
|
424
|
+
File.new(file, "w").puts content
|
425
|
+
end
|
426
|
+
|
427
|
+
end
|
428
|
+
|
429
|
+
|
430
|
+
# <link rel="stylesheet" type="text/css" href="/stylesheets/default.css" />
|
431
|
+
# '<script type="text/javascript" src="http://www.jeroenwijering.com/embed/swfobject.js"></script>'
|
432
|
+
# <script type="text/javascript" src="/javascripts/prototype.js"></script>
|
433
|
+
# <script type="text/javascript" src="/javascripts/scriptaculous.js?load=effects,builder"></script>
|
434
|
+
# <script type="text/javascript" src="/javascripts/extensions/gallery/lightbox.js"></script>
|
435
|
+
# <link href="/stylesheets/extensions/gallery/lightbox.css" rel="stylesheet" type="text/css" />
|
436
|
+
# <img src="images/mission_48.png" />
|
437
|
+
def absolutize_page(content, base_url, current_url_parent)
|
438
|
+
modified_content = ""
|
439
|
+
content.each_line do |line|
|
440
|
+
if line =~ /<script\s+.*src=["'']?(.*)["'].*/i then
|
441
|
+
script_src = $1
|
442
|
+
substitute_relative_path_in_src_line(line, script_src, base_url, current_url_parent)
|
443
|
+
elsif line =~ /<link\s+.*href=["'']?(.*)["'].*/i then
|
444
|
+
link_href = $1
|
445
|
+
substitute_relative_path_in_src_line(line, link_href, base_url, current_url_parent)
|
446
|
+
elsif line =~ /<img\s+.*src=["'']?(.*)["'].*/i then
|
447
|
+
img_src = $1
|
448
|
+
substitute_relative_path_in_src_line(line, img_src, base_url, current_url_parent)
|
449
|
+
end
|
450
|
+
|
451
|
+
modified_content += line
|
452
|
+
end
|
453
|
+
return modified_content
|
454
|
+
end
|
455
|
+
|
456
|
+
# absolutize_page referencs using hpricot
|
457
|
+
#
|
458
|
+
def absolutize_page_hpricot(content, base_url, parent_url)
|
459
|
+
return absolutize_page(content, base_url, parent_url) if RUBY_PLATFORM == 'java'
|
460
|
+
begin
|
461
|
+
require 'nokogiri'
|
462
|
+
doc = Nokogiri::HTML(content)
|
463
|
+
base_url.slice!(-1) if ends_with?(base_url, "/")
|
464
|
+
(doc/'link').each { |e| e['href'] = absolutify_url(e['href'], base_url, parent_url) || "" }
|
465
|
+
(doc/'img').each { |e| e['src'] = absolutify_url(e['src'], base_url, parent_url) || "" }
|
466
|
+
(doc/'script').each { |e| e['src'] = absolutify_url(e['src'], base_url, parent_url) || "" }
|
467
|
+
return doc.to_html
|
468
|
+
rescue => e
|
469
|
+
absolutize_page(content, base_url, parent_url)
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
##
|
474
|
+
# change
|
475
|
+
# <script type="text/javascript" src="/javascripts/prototype.js"></script>
|
476
|
+
# to
|
477
|
+
# <script type="text/javascript" src="http://itest2.com/javascripts/prototype.js"></script>
|
478
|
+
def absolutify_url(src, base_url, parent_url)
|
479
|
+
if src.nil? || src.empty? || src == "//:" || src =~ /\s*http:\/\//i
|
480
|
+
return src
|
481
|
+
end
|
482
|
+
|
483
|
+
return "#{base_url}#{src}" if src =~ /^\s*\//
|
484
|
+
return "#{parent_url}#{src}" if parent_url
|
485
|
+
return src
|
486
|
+
end
|
487
|
+
|
488
|
+
# substut
|
489
|
+
def substitute_relative_path_in_src_line(line, script_src, host_url, page_parent_url)
|
490
|
+
unless script_src =~ /^["']?http:/
|
491
|
+
host_url.slice!(-1) if ends_with?(host_url, "/")
|
492
|
+
if script_src =~ /^\s*\// # absolute_path
|
493
|
+
line.gsub!(script_src, "#{host_url}#{script_src}")
|
494
|
+
else #relative_path
|
495
|
+
line.gsub!(script_src, "#{page_parent_url}#{script_src}")
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
def ends_with?(str, suffix)
|
501
|
+
suffix = suffix.to_s
|
502
|
+
str[-suffix.length, suffix.length] == suffix
|
503
|
+
end
|
504
|
+
|
505
|
+
# current web page title
|
506
|
+
def page_title
|
507
|
+
@web_browser.page_title
|
508
|
+
end
|
509
|
+
|
510
|
+
# current page source (in HTML)
|
511
|
+
def page_source
|
512
|
+
@web_browser.page_source
|
513
|
+
end
|
514
|
+
|
515
|
+
# return plain text view of page
|
516
|
+
def page_text
|
517
|
+
@web_browser.text
|
518
|
+
end
|
519
|
+
|
520
|
+
# return the text of specific (identified by attribute "id") label tag
|
521
|
+
# For page containing
|
522
|
+
# <label id="preferred_ide">TestWise</label>
|
523
|
+
# label_with_id("preferred_ids") # => TestWise
|
524
|
+
# label_with_id("preferred_ids", :index => 2) # => TestWise
|
525
|
+
def label_with_id(label_id, options = {})
|
526
|
+
if options && options[:index] then
|
527
|
+
elements = find_elements(:id, label_id.to_s)
|
528
|
+
elements[options[:index].to_i - 1].text
|
529
|
+
# label(:id => label_id.to_s, :index => options[:index]).text
|
530
|
+
else
|
531
|
+
find_element(:id, label_id.to_s).text
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
# return the text of specific (identified by attribute "id") span tag
|
536
|
+
# For page containing
|
537
|
+
# <span id="preferred_recorder">iTest2/Watir Recorder</span>
|
538
|
+
# span_with_id("preferred_recorder") # => iTest2/Watir Recorder
|
539
|
+
def span_with_id(span_id, options = {})
|
540
|
+
if options && options[:index] then
|
541
|
+
elements = find_elements(:id, span_id.to_s)
|
542
|
+
elements[options[:index].to_i - 1].text
|
543
|
+
else
|
544
|
+
find_element(:id, span_id.to_s).text
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
# return the text of specific (identified by attribute "id") ta tag
|
549
|
+
# For page containing
|
550
|
+
# <td id="preferred_recorder">iTest2/Watir Recorder</span>
|
551
|
+
# td_with_id("preferred_recorder") # => iTest2/Watir Recorder
|
552
|
+
def cell_with_id(cell_id, options = {})
|
553
|
+
if options && options[:index] then
|
554
|
+
elements = find_elements(:id, cell_id.to_s)
|
555
|
+
elements[options[:index].to_i - 1].text
|
556
|
+
else
|
557
|
+
find_element(:id, cell_id.to_s).text
|
558
|
+
end
|
559
|
+
end
|
560
|
+
alias table_data_with_id cell_with_id
|
561
|
+
|
562
|
+
|
563
|
+
def is_mac?
|
564
|
+
RUBY_PLATFORM.downcase.include?("darwin")
|
565
|
+
end
|
566
|
+
|
567
|
+
def is_windows?
|
568
|
+
RUBY_PLATFORM.downcase.include?("mswin") or RUBY_PLATFORM.downcase.include?("mingw")
|
569
|
+
end
|
570
|
+
|
571
|
+
def is_linux?
|
572
|
+
RUBY_PLATFORM.downcase.include?("linux")
|
573
|
+
end
|
574
|
+
|
575
|
+
# Support browser (IE) operations using unicode
|
576
|
+
# Example:
|
577
|
+
# click_button("Google 搜索")
|
578
|
+
# Reference: http://jira.openqa.org/browse/WTR-219
|
579
|
+
def support_utf8
|
580
|
+
if is_windows?
|
581
|
+
require 'win32ole'
|
582
|
+
WIN32OLE.codepage = WIN32OLE::CP_UTF8
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
586
|
+
alias support_unicode support_utf8
|
587
|
+
|
588
|
+
#= Convenient functions
|
589
|
+
#
|
590
|
+
|
591
|
+
# Using Ruby block syntax to create interesting domain specific language,
|
592
|
+
# may be appeal to someone.
|
593
|
+
|
594
|
+
# Example:
|
595
|
+
# on @page do |i|
|
596
|
+
# i.enter_text('btn1')
|
597
|
+
# i.click_button('btn1')
|
598
|
+
# end
|
599
|
+
def on(page, & block)
|
600
|
+
yield page
|
601
|
+
end
|
602
|
+
|
603
|
+
# fail the test if user can perform the operation
|
604
|
+
#
|
605
|
+
# Example:
|
606
|
+
# shall_not_allow { 1/0 }
|
607
|
+
def shall_not_allow(& block)
|
608
|
+
operation_performed_ok = false
|
609
|
+
begin
|
610
|
+
yield
|
611
|
+
operation_performed_ok = true
|
612
|
+
rescue
|
613
|
+
end
|
614
|
+
raise "Operation shall not be allowed" if operation_performed_ok
|
615
|
+
end
|
616
|
+
|
617
|
+
alias do_not_allow shall_not_allow
|
618
|
+
|
619
|
+
# Does not provide real function, other than make enhancing test syntax
|
620
|
+
#
|
621
|
+
# Example:
|
622
|
+
# allow { click_button('Register') }
|
623
|
+
def allow(& block)
|
624
|
+
yield
|
625
|
+
end
|
626
|
+
|
627
|
+
alias shall_allow allow
|
628
|
+
alias allowing allow
|
629
|
+
|
630
|
+
# try operation, ignore if errors occur
|
631
|
+
#
|
632
|
+
# Example:
|
633
|
+
# failsafe { click_link("Logout") } # try logout, but it still OK if not being able to (already logout))
|
634
|
+
def failsafe(& block)
|
635
|
+
begin
|
636
|
+
yield
|
637
|
+
rescue =>e
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
alias fail_safe failsafe
|
642
|
+
|
643
|
+
|
644
|
+
# Execute the provided block until either (1) it returns true, or
|
645
|
+
# (2) the timeout (in seconds) has been reached. If the timeout is reached,
|
646
|
+
# a TimeOutException will be raised. The block will always
|
647
|
+
# execute at least once.
|
648
|
+
#
|
649
|
+
# This does not handle error, if the given block raise error, the statement finish with error
|
650
|
+
# Examples:
|
651
|
+
# wait_until {puts 'hello'}
|
652
|
+
# wait_until { div(:id, :receipt_date).exists? }
|
653
|
+
#
|
654
|
+
def wait_until(timeout = @@default_timeout || 30, polling_interval = @@default_polling_interval || 1, & block)
|
655
|
+
end_time = ::Time.now + timeout
|
656
|
+
|
657
|
+
until ::Time.now > end_time
|
658
|
+
result = nil
|
659
|
+
begin
|
660
|
+
result = yield(self)
|
661
|
+
return result if result
|
662
|
+
rescue => e
|
663
|
+
end
|
664
|
+
sleep polling_interval
|
665
|
+
end
|
666
|
+
|
667
|
+
raise TimeoutError, "timed out after #{timeout} seconds"
|
668
|
+
end
|
669
|
+
|
670
|
+
# Wait for specific seconds for an Ajax update finish.
|
671
|
+
# Trick: In your Rails application,
|
672
|
+
# :loading => "Element.show('search_indicator');
|
673
|
+
# :complete => "Element.hide('search_indicator');
|
674
|
+
#
|
675
|
+
# <%= image_tag("indicator.gif", :id => 'search_indicator', :style => 'display:none') %>
|
676
|
+
#
|
677
|
+
# Typical usage:
|
678
|
+
# ajax_wait_for_element("search_indicator", 30)
|
679
|
+
# ajax_wait_for_element("search_indicator", 30, "show")
|
680
|
+
# ajax_wait_for_element("search_indicator", 30, "hide")
|
681
|
+
# ajax_wait_for_element("search_indicator", 30, "show", 5) # check every 5 seconds
|
682
|
+
#
|
683
|
+
# Warning: this method has not been fully tested, if you are not using Rails, change your parameter accordingly.
|
684
|
+
#
|
685
|
+
def ajax_wait_for_element(element_id, seconds, status='show', check_interval = @@default_polling_interval)
|
686
|
+
count = 0
|
687
|
+
check_interval = 1 if check_interval < 1 or check_interval > seconds
|
688
|
+
while count < (seconds / check_interval) do
|
689
|
+
search_indicator = @web_browser.element_by_id(element_id)
|
690
|
+
search_indicator_outer_html = search_indicator.outerHtml if search_indicator
|
691
|
+
if status == 'hide'
|
692
|
+
return true if search_indicator_outer_html and !search_indicator_outer_html.include?('style="DISPLAY: none"')
|
693
|
+
else
|
694
|
+
return true if search_indicator_outer_html and search_indicator_outer_html.include?('style="DISPLAY: none"')
|
695
|
+
end
|
696
|
+
sleep check_interval if check_interval > 0 and check_interval < 5 * 60 # wait max 5 minutes
|
697
|
+
count += 1
|
698
|
+
end
|
699
|
+
return false
|
700
|
+
end
|
701
|
+
|
702
|
+
#Wait the element with given id to be present in web page
|
703
|
+
#
|
704
|
+
# Warning: this not working in Firefox, try use wait_util or try instead
|
705
|
+
def wait_for_element(element_id, timeout = @@default_timeout, interval = @@default_polling_interval)
|
706
|
+
start_time = Time.now
|
707
|
+
#TODO might not work with Firefox
|
708
|
+
until @web_browser.element_by_id(element_id) do
|
709
|
+
sleep(interval)
|
710
|
+
if (Time.now - start_time) > timeout
|
711
|
+
raise RuntimeError, "failed to find element: #{element_id} for max #{timeout}"
|
712
|
+
end
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
=begin
|
717
|
+
|
718
|
+
# TODO: Firewatir does not suport retrieving style or outerHtml
|
719
|
+
# http://jira.openqa.org/browse/WTR-260
|
720
|
+
# http://code.google.com/p/firewatir/issues/detail?id=76
|
721
|
+
#
|
722
|
+
# Max timeout value is 10 minutes
|
723
|
+
#
|
724
|
+
def ajax_call_complete_after_element_hidden(elem_id, check_start = 0.5, timeout = 5, interval = 0.5, &block)
|
725
|
+
yield
|
726
|
+
sleep check_start # the time allowed to perform the coomplete
|
727
|
+
timeout = 10 * 60 if timeout > 10 * 600 or timeout <= 0
|
728
|
+
begin
|
729
|
+
Timeout::timeout(timeout) {
|
730
|
+
begin
|
731
|
+
elem = element_by_id(elem_id)
|
732
|
+
while elem do
|
733
|
+
puts "outer=>#{elem.outerHtml}|"
|
734
|
+
puts "style =>#{elem.attribute_value('style')}|"
|
735
|
+
sleep interval
|
736
|
+
elem = element_by_id(elem_id)
|
737
|
+
end
|
738
|
+
rescue => e
|
739
|
+
puts e
|
740
|
+
end
|
741
|
+
}
|
742
|
+
rescue Timeout::Error
|
743
|
+
# Too slow!!
|
744
|
+
raise "Too slow, wait max #{timeout} seconds, the element #{elem_id} still there"
|
745
|
+
end
|
746
|
+
end
|
747
|
+
|
748
|
+
=end
|
749
|
+
|
750
|
+
# Try the operation up to specified times, and sleep given interval (in seconds)
|
751
|
+
# Error will be ignored until timeout
|
752
|
+
# Example
|
753
|
+
# repeat_try(3, 2) { click_button('Search' } # 3 times, 6 seconds in total
|
754
|
+
# repeat_try { click_button('Search' } # using default 5 tries, 2 second interval
|
755
|
+
def repeat_try(num_tries = @@default_timeout || 30, interval = @@default_polling_interval || 1, & block)
|
756
|
+
num_tries ||= 1
|
757
|
+
(num_tries - 1).times do |num|
|
758
|
+
begin
|
759
|
+
yield
|
760
|
+
return
|
761
|
+
rescue => e
|
762
|
+
# puts "debug: #{num} failed: #{e}"
|
763
|
+
sleep interval
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
767
|
+
# last try, throw error if still fails
|
768
|
+
begin
|
769
|
+
yield
|
770
|
+
rescue => e
|
771
|
+
raise e.to_s + " after trying #{num_tries} times every #{interval} seconds"
|
772
|
+
end
|
773
|
+
yield
|
774
|
+
end
|
775
|
+
|
776
|
+
# TODO: syntax
|
777
|
+
|
778
|
+
# Try the operation up to specified timeout (in seconds), and sleep given interval (in seconds).
|
779
|
+
# Error will be ignored until timeout
|
780
|
+
# Example
|
781
|
+
# try { click_link('waiting')}
|
782
|
+
# try(10, 2) { click_button('Search' } # try to click the 'Search' button upto 10 seconds, try every 2 seconds
|
783
|
+
# try { click_button('Search' }
|
784
|
+
def try(timeout = @@default_timeout, polling_interval = @@default_polling_interval || 1, & block)
|
785
|
+
start_time = Time.now
|
786
|
+
|
787
|
+
last_error = nil
|
788
|
+
until (duration = Time.now - start_time) > timeout
|
789
|
+
begin
|
790
|
+
return if yield
|
791
|
+
last_error = nil
|
792
|
+
rescue => e
|
793
|
+
last_error = e
|
794
|
+
end
|
795
|
+
sleep polling_interval
|
796
|
+
end
|
797
|
+
|
798
|
+
raise "Timeout after #{duration.to_i} seconds with error: #{last_error}." if last_error
|
799
|
+
raise "Timeout after #{duration.to_i} seconds."
|
800
|
+
end
|
801
|
+
|
802
|
+
alias try_upto try
|
803
|
+
|
804
|
+
##
|
805
|
+
# Convert :first to 1, :second to 2, and so on...
|
806
|
+
def symbol_to_sequence(symb)
|
807
|
+
value = {:zero => 0,
|
808
|
+
:first => 1,
|
809
|
+
:second => 2,
|
810
|
+
:third => 3,
|
811
|
+
:fourth => 4,
|
812
|
+
:fifth => 5,
|
813
|
+
:sixth => 6,
|
814
|
+
:seventh => 7,
|
815
|
+
:eighth => 8,
|
816
|
+
:ninth => 9,
|
817
|
+
:tenth => 10}[symb]
|
818
|
+
return value || symb.to_i
|
819
|
+
end
|
820
|
+
|
821
|
+
# Clear popup windows such as 'Security Alert' or 'Security Information' popup window,
|
822
|
+
#
|
823
|
+
# Screenshot see http://kb2.adobe.com/cps/165/tn_16588.html
|
824
|
+
#
|
825
|
+
# You can also by pass security alerts by change IE setting, http://kb.iu.edu/data/amuj.html
|
826
|
+
#
|
827
|
+
# Example
|
828
|
+
# clear_popup("Security Information", 5, true) # check for Security Information for 5 seconds, click Yes
|
829
|
+
def clear_popup(popup_win_title, seconds = 10, yes = true)
|
830
|
+
# commonly "Security Alert", "Security Information"
|
831
|
+
if is_windows?
|
832
|
+
sleep 1
|
833
|
+
autoit = WIN32OLE.new('AutoItX3.Control')
|
834
|
+
# Look for window with given title. Give up after 1 second.
|
835
|
+
ret = autoit.WinWait(popup_win_title, '', seconds)
|
836
|
+
#
|
837
|
+
# If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).
|
838
|
+
if ret == 1 then
|
839
|
+
puts "about to send click Yes" if debugging?
|
840
|
+
button_id = yes ? "Button1" : "Button2" # Yes or No
|
841
|
+
autoit.ControlClick(popup_win_title, '', button_id)
|
842
|
+
end
|
843
|
+
sleep(0.5)
|
844
|
+
else
|
845
|
+
raise "Currently supported only on Windows"
|
846
|
+
end
|
847
|
+
end
|
848
|
+
|
849
|
+
def select_file_for_upload(file_field_name, file_path)
|
850
|
+
=begin
|
851
|
+
if is_windows?
|
852
|
+
normalized_file_path = file_path.gsub("/", "\\")
|
853
|
+
if $support_ie8 && check_ie_version && @ie_version >= 8
|
854
|
+
# puts "IE8"
|
855
|
+
file_field(:name, file_field).set(normalized_file_path)
|
856
|
+
# choose_file_dialog(normalized_file_path)
|
857
|
+
else
|
858
|
+
file_field(:name, file_field).set(normalized_file_path)
|
859
|
+
end
|
860
|
+
else
|
861
|
+
# for firefox, just call file_field, it may fail
|
862
|
+
file_field(:name, file_field).set(normalized_file_path)
|
863
|
+
end
|
864
|
+
=end
|
865
|
+
elem = find_element(:name, file_field_name)
|
866
|
+
elem.send_keys(file_path)
|
867
|
+
end
|
868
|
+
|
869
|
+
def choose_file_dialog(file_path)
|
870
|
+
Watir.autoit.WinWaitActive("Choose File to Upload", '', 10)
|
871
|
+
Watir.autoit.ControlSetText("Choose File to Upload", "", 1148, file_path)
|
872
|
+
Watir.autoit.ControlClick("Choose File to Upload", "", "&Open")
|
873
|
+
end
|
874
|
+
|
875
|
+
def check_ie_version
|
876
|
+
if is_windows? && @ie_version.nil?
|
877
|
+
begin
|
878
|
+
cmd = 'reg query "HKLM\SOFTWARE\Microsoft\Internet Explorer" /v Version';
|
879
|
+
result = `#{cmd}`
|
880
|
+
version_line = nil
|
881
|
+
result.each do |line|
|
882
|
+
if (line =~ /Version\s+REG_SZ\s+([\d\.]+)/)
|
883
|
+
version_line = $1
|
884
|
+
end
|
885
|
+
end
|
886
|
+
|
887
|
+
if version_line =~ /^\s*(\d+)\./
|
888
|
+
@ie_version = $1.to_i
|
889
|
+
end
|
890
|
+
rescue => e
|
891
|
+
end
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
895
|
+
# Use AutoIT3 to send password
|
896
|
+
# title starts with "Connect to ..."
|
897
|
+
def basic_authentication_ie(title, username, password, options = {})
|
898
|
+
default_options = {:textctrl_username => "Edit2",
|
899
|
+
:textctrl_password => "Edit3",
|
900
|
+
:button_ok => 'Button1'
|
901
|
+
}
|
902
|
+
|
903
|
+
options = default_options.merge(options)
|
904
|
+
|
905
|
+
title ||= ""
|
906
|
+
if title =~ /^Connect\sto/
|
907
|
+
full_title = title
|
908
|
+
else
|
909
|
+
full_title = "Connect to #{title}"
|
910
|
+
end
|
911
|
+
require 'rformspec'
|
912
|
+
login_win = RFormSpec::Window.new(full_title)
|
913
|
+
login_win.send_control_text(options[:textctrl_username], username)
|
914
|
+
login_win.send_control_text(options[:textctrl_password], password)
|
915
|
+
login_win.click_button("OK")
|
916
|
+
end
|
917
|
+
|
918
|
+
# Use JSSH to pass authentication
|
919
|
+
# Window title "Authentication required"
|
920
|
+
def basic_authentication_firefox(username, password, wait = 3)
|
921
|
+
jssh_command = "
|
922
|
+
var length = getWindows().length;
|
923
|
+
var win;
|
924
|
+
var found = false;
|
925
|
+
for (var i = 0; i < length; i++) {
|
926
|
+
win = getWindows()[i];
|
927
|
+
if(win.document.title == \"Authentication Required\") {
|
928
|
+
found = true;
|
929
|
+
break;
|
930
|
+
}
|
931
|
+
}
|
932
|
+
if (found) {
|
933
|
+
var jsdocument = win.document;
|
934
|
+
var dialog = jsdocument.getElementsByTagName(\"dialog\")[0];
|
935
|
+
jsdocument.getElementsByTagName(\"textbox\")[0].value = \"#{username}\";
|
936
|
+
jsdocument.getElementsByTagName(\"textbox\")[1].value = \"#{password}\";
|
937
|
+
dialog.getButton(\"accept\").click();
|
938
|
+
}
|
939
|
+
\n"
|
940
|
+
sleep(wait)
|
941
|
+
$jssh_socket.send(jssh_command, 0)
|
942
|
+
# read_socket()
|
943
|
+
end
|
944
|
+
|
945
|
+
def basic_authentication_celerity(username, password)
|
946
|
+
@web_browser.celerity.credentials = "#{username}:#{password}"
|
947
|
+
end
|
948
|
+
|
949
|
+
def basic_authentication(username, password, options = {})
|
950
|
+
if is_celerity?
|
951
|
+
basic_authentication_celerity(username, password)
|
952
|
+
elsif is_firefox?
|
953
|
+
basic_authentication_firefox(username, password)
|
954
|
+
else
|
955
|
+
basic_authentication_ie(options[:title], username, password, options)
|
956
|
+
end
|
957
|
+
end
|
958
|
+
|
959
|
+
# take_screenshot to save the current active window
|
960
|
+
# TODO can't move mouse
|
961
|
+
def take_screenshot_old
|
962
|
+
if is_windows? && $ITEST2_DUMP_PAGE
|
963
|
+
begin
|
964
|
+
puts "[DEBUG] Capturing screenshots..."
|
965
|
+
screenshot_image_filename = "rwebspec_" + Time.now.strftime("%m%d%H%M%S") + ".jpg"
|
966
|
+
the_dump_dir = default_dump_dir
|
967
|
+
FileUtils.mkdir_p(the_dump_dir) unless File.exists?(the_dump_dir)
|
968
|
+
screenshot_image_filepath = File.join(the_dump_dir, screenshot_image_filename)
|
969
|
+
|
970
|
+
screenshot_image_filepath.gsub!("/", "\\") if is_windows?
|
971
|
+
screen_capture(screenshot_image_filepath, true)
|
972
|
+
|
973
|
+
notify_screenshot_location(screenshot_image_filepath)
|
974
|
+
rescue
|
975
|
+
puts "error: #{Failed to capture screen}"
|
976
|
+
end
|
977
|
+
end
|
978
|
+
end
|
979
|
+
|
980
|
+
|
981
|
+
# use win32screenshot library to save curernt active window, which shall be IE
|
982
|
+
#
|
983
|
+
def take_screenshot
|
984
|
+
if $testwise_screenshot_supported && is_windows?
|
985
|
+
begin
|
986
|
+
screenshot_image_filename = "screenshot_" + Time.now.strftime("%m%d%H%M%S") + ".jpg"
|
987
|
+
the_dump_dir = default_dump_dir
|
988
|
+
FileUtils.mkdir_p(the_dump_dir) unless File.exists?(the_dump_dir)
|
989
|
+
screenshot_image_filepath = File.join(the_dump_dir, screenshot_image_filename)
|
990
|
+
screenshot_image_filepath.gsub!("/", "\\") if is_windows?
|
991
|
+
|
992
|
+
FileUtils.rm_f(screenshot_image_filepath) if File.exist?(screenshot_image_filepath)
|
993
|
+
|
994
|
+
case @web_browser.underlying_browser.browser
|
995
|
+
when :internet_explorer
|
996
|
+
Win32::Screenshot::Take.of(:window, :title => /internet\sexplorer/i).write(screenshot_image_filepath)
|
997
|
+
else
|
998
|
+
Win32::Screenshot::Take.of(:foreground).write(screenshot_image_filepath)
|
999
|
+
end
|
1000
|
+
notify_screenshot_location(screenshot_image_filepath)
|
1001
|
+
rescue => e
|
1002
|
+
puts "error on taking screenshot: #{e}"
|
1003
|
+
end
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
end
|