rwebspec-webdriver 0.1.1 → 0.1.2

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