warnold-selenium-client 1.2.19

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.
Files changed (33) hide show
  1. data/README.markdown +338 -0
  2. data/examples/rspec/google_spec.rb +41 -0
  3. data/examples/script/google.rb +25 -0
  4. data/examples/testunit/google_test.rb +39 -0
  5. data/lib/nautilus/shell.rb +34 -0
  6. data/lib/selenium.rb +14 -0
  7. data/lib/selenium/client.rb +27 -0
  8. data/lib/selenium/client/base.rb +118 -0
  9. data/lib/selenium/client/driver.rb +11 -0
  10. data/lib/selenium/client/extensions.rb +118 -0
  11. data/lib/selenium/client/idiomatic.rb +488 -0
  12. data/lib/selenium/client/javascript_expression_builder.rb +116 -0
  13. data/lib/selenium/client/javascript_frameworks/jquery.rb +13 -0
  14. data/lib/selenium/client/javascript_frameworks/prototype.rb +13 -0
  15. data/lib/selenium/client/legacy_driver.rb +1711 -0
  16. data/lib/selenium/client/protocol.rb +104 -0
  17. data/lib/selenium/client/selenium_helper.rb +34 -0
  18. data/lib/selenium/command_error.rb +4 -0
  19. data/lib/selenium/protocol_error.rb +4 -0
  20. data/lib/selenium/rake/default_tasks.rb +17 -0
  21. data/lib/selenium/rake/remote_control_start_task.rb +71 -0
  22. data/lib/selenium/rake/remote_control_stop_task.rb +44 -0
  23. data/lib/selenium/rake/tasks.rb +6 -0
  24. data/lib/selenium/remote_control/remote_control.rb +35 -0
  25. data/lib/selenium/rspec/reporting/file_path_strategy.rb +78 -0
  26. data/lib/selenium/rspec/reporting/html_report.rb +155 -0
  27. data/lib/selenium/rspec/reporting/selenium_test_report_formatter.rb +88 -0
  28. data/lib/selenium/rspec/reporting/system_capture.rb +72 -0
  29. data/lib/selenium/rspec/rspec_extensions.rb +104 -0
  30. data/lib/selenium/rspec/spec_helper.rb +34 -0
  31. data/lib/tcp_socket_extension.rb +32 -0
  32. data/test/all_unit_tests.rb +3 -0
  33. metadata +102 -0
@@ -0,0 +1,14 @@
1
+ # Legacy helper providing backward compatibility
2
+
3
+ # -----------------
4
+ # Original code by Aslak Hellesoy and Darren Hobbs
5
+ # This file has been automatically generated via XSL
6
+ # -----------------
7
+
8
+ require File.expand_path(File.dirname(__FILE__) + '/selenium/client')
9
+
10
+ # Backward compatibility
11
+
12
+ SeleniumHelper = Selenium::Client::SeleniumHelper
13
+ SeleniumCommandError = Selenium::CommandError
14
+ Selenium::SeleniumDriver = Selenium::Client::Driver
@@ -0,0 +1,27 @@
1
+ #
2
+ # Helper requiring the basic selenium-client API (no RSpec goodness)
3
+ #
4
+
5
+ require 'net/http'
6
+ require 'uri'
7
+ require 'cgi'
8
+ require "digest/md5"
9
+ require 'fileutils'
10
+ require 'tmpdir'
11
+ require File.expand_path(File.dirname(__FILE__) + '/../tcp_socket_extension')
12
+ require File.expand_path(File.dirname(__FILE__) + '/../nautilus/shell')
13
+ require File.expand_path(File.dirname(__FILE__) + '/command_error')
14
+ require File.expand_path(File.dirname(__FILE__) + '/protocol_error')
15
+ require File.expand_path(File.dirname(__FILE__) + '/client/protocol')
16
+ require File.expand_path(File.dirname(__FILE__) + '/client/legacy_driver')
17
+ require File.expand_path(File.dirname(__FILE__) + '/client/javascript_expression_builder')
18
+ require File.expand_path(File.dirname(__FILE__) + '/client/javascript_frameworks/prototype')
19
+ require File.expand_path(File.dirname(__FILE__) + '/client/javascript_frameworks/jquery')
20
+ require File.expand_path(File.dirname(__FILE__) + '/client/extensions')
21
+ require File.expand_path(File.dirname(__FILE__) + '/client/idiomatic')
22
+ require File.expand_path(File.dirname(__FILE__) + '/client/base')
23
+ require File.expand_path(File.dirname(__FILE__) + '/client/driver')
24
+ require File.expand_path(File.dirname(__FILE__) + '/client/selenium_helper')
25
+ require File.expand_path(File.dirname(__FILE__) + '/remote_control/remote_control')
26
+ require File.expand_path(File.dirname(__FILE__) + '/rake/remote_control_start_task')
27
+ require File.expand_path(File.dirname(__FILE__) + '/rake/remote_control_stop_task')
@@ -0,0 +1,118 @@
1
+ module Selenium
2
+ module Client
3
+
4
+ # Driver constructor and session management commands
5
+ module Base
6
+ include Selenium::Client::Protocol
7
+ include Selenium::Client::GeneratedDriver
8
+ include Selenium::Client::Extensions
9
+ include Selenium::Client::Idiomatic
10
+
11
+ attr_reader :host, :port, :browser_string, :browser_url,
12
+ :default_timeout_in_seconds,
13
+ :default_javascript_framework,
14
+ :highlight_located_element_by_default
15
+
16
+ #
17
+ # Create a new client driver
18
+ #
19
+ # Example:
20
+ #
21
+ # Selenium::Client::Driver.new \
22
+ # :host => "localhost",
23
+ # :port => 4444,
24
+ # :browser => "*firefox",
25
+ # :timeout_in_seconds => 10,
26
+ # :url => "http://localhost:3000",
27
+ #
28
+ # You can also set the default javascript framework used for :wait_for
29
+ # AJAX and effects semantics (:prototype is the default value):
30
+ #
31
+ # Selenium::Client::Driver.new \
32
+ # :host => "localhost",
33
+ # :port => 4444,
34
+ # :browser => "*firefox",
35
+ # :timeout_in_seconds => 10,
36
+ # :url => "http://localhost:3000",
37
+ # :javascript_framework => :jquery
38
+ #
39
+ # You can also enables automatic highlighting of located elements
40
+ # by passing the highlight_located_element option, e.g.
41
+ #
42
+ # Selenium::Client::Driver.new \
43
+ # :host => "localhost",
44
+ # :port => 4444,
45
+ # :browser => "*firefox",
46
+ # :highlight_located_element => true
47
+ #
48
+ def initialize(*args)
49
+ if args[0].kind_of?(Hash)
50
+ options = args[0]
51
+ @host = options[:host]
52
+ @port = options[:port].to_i
53
+ @browser_string = options[:browser]
54
+ @browser_url = options[:url]
55
+ @default_timeout_in_seconds = (options[:timeout_in_seconds] || 300).to_i
56
+ @default_javascript_framework = options[:javascript_framework] || :prototype
57
+ @highlight_located_element_by_default = options[:highlight_located_element] || false
58
+ else
59
+ @host = args[0]
60
+ @port = args[1].to_i
61
+ @browser_string = args[2]
62
+ @browser_url = args[3]
63
+ @default_timeout_in_seconds = (args[4] || 300).to_i
64
+ @default_javascript_framework = :prototype
65
+ @highlight_located_element_by_default = false
66
+ end
67
+
68
+ @extension_js = ""
69
+ @session_id = nil
70
+ end
71
+
72
+ def session_started?
73
+ not @session_id.nil?
74
+ end
75
+
76
+ # Starts a new browser session (launching a new browser matching
77
+ # configuration provided at driver creation time).
78
+ #
79
+ # Browser session specific option can also be provided. e.g.
80
+ #
81
+ # driver.start_new_browser_session(:captureNetworkTraffic => true)
82
+ #
83
+ def start_new_browser_session(options={})
84
+ options_as_string = options.collect {|key,value| "#{key.to_s}=#{value.to_s}"}.sort.join(";")
85
+ result = string_command "getNewBrowserSession", [@browser_string, @browser_url, @extension_js, options_as_string]
86
+ @session_id = result
87
+ # Consistent timeout on the remote control and driver side.
88
+ # Intuitive and this is what you want 90% of the time
89
+ self.remote_control_timeout_in_seconds = @default_timeout_in_seconds
90
+ self.highlight_located_element = true if highlight_located_element_by_default
91
+ end
92
+
93
+ def close_current_browser_session
94
+ remote_control_command "testComplete" if @session_id
95
+ @session_id = nil
96
+ end
97
+
98
+ def start
99
+ start_new_browser_session
100
+ end
101
+
102
+ def stop
103
+ close_current_browser_session
104
+ end
105
+
106
+ def chrome_backend?
107
+ ["*chrome", "*firefox", "*firefox2", "*firefox3"].include?(@browser_string)
108
+ end
109
+
110
+ def javascript_extension=(new_javascript_extension)
111
+ @extension_js = new_javascript_extension
112
+ end
113
+ alias :set_extension_js :javascript_extension=
114
+
115
+ end
116
+
117
+ end
118
+ end
@@ -0,0 +1,11 @@
1
+ module Selenium
2
+ module Client
3
+
4
+ # Client driver providing the complete API to drive a Selenium Remote Control
5
+ class Driver
6
+ include Selenium::Client::Base
7
+
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,118 @@
1
+ module Selenium
2
+ module Client
3
+
4
+ # Convenience methods not explicitely part of the protocol
5
+ module Extensions
6
+
7
+ # These for all Ajax request to finish (Only works if you are using prototype, the wait happens in the browser)
8
+ #
9
+ # See http://davidvollbracht.com/2008/6/4/30-days-of-tech-day-3-waitforajax for
10
+ # more background.
11
+ def wait_for_ajax(options={})
12
+ builder = JavascriptExpressionBuilder.new active_javascript_framework(options)
13
+ wait_for_condition builder.no_pending_ajax_requests.script,
14
+ options[:timeout_in_seconds]
15
+ end
16
+
17
+ # Wait for all Prototype effects to be processed (the wait happens in the browser).
18
+ #
19
+ # Credits to http://github.com/brynary/webrat/tree/master
20
+ def wait_for_effects(options={})
21
+ builder = JavascriptExpressionBuilder.new active_javascript_framework(options)
22
+ wait_for_condition builder.no_pending_effects.script,
23
+ options[:timeout_in_seconds]
24
+ end
25
+
26
+ # Wait for an element to be present (the wait happens in the browser).
27
+ def wait_for_element(locator, options={})
28
+ builder = JavascriptExpressionBuilder.new
29
+ builder.find_element(locator).append("element != null;")
30
+ wait_for_condition builder.script, options[:timeout_in_seconds]
31
+ end
32
+
33
+ # Wait for an element to NOT be present (the wait happens in the browser).
34
+ def wait_for_no_element(locator, options={})
35
+ builder = JavascriptExpressionBuilder.new
36
+ builder.find_element(locator).append("element == null;")
37
+ wait_for_condition builder.script, options[:timeout_in_seconds]
38
+ end
39
+
40
+ # Wait for some text to be present (the wait is happening browser side).
41
+ #
42
+ # wait_for_text will search for the given argument within the innerHTML
43
+ # of the current DOM. Note that this method treats a single string
44
+ # as a special case.
45
+ #
46
+ # ==== Parameters
47
+ # wait_for_text accepts an optional hash of parameters:
48
+ # * <tt>:element</tt> - a selenium locator for an element limiting
49
+ # the search scope.
50
+ # * <tt>:timeout_in_seconds</tt> - duration in seconds after which we
51
+ # time out if text cannot be found.
52
+ #
53
+ # ==== Regular Expressions
54
+ # In addition to plain strings, wait_for_text accepts regular expressions
55
+ # as the pattern specification.
56
+ #
57
+ # ==== Examples
58
+ # The following are equivalent, and will match "some text" anywhere
59
+ # within the document:
60
+ # wait_for_text "some text"
61
+ # wait_for_text /some text/
62
+ #
63
+ # This will match "some text" anywhere within the specified element:
64
+ # wait_for_text /some text/, :element => "container"
65
+ #
66
+ # This will match "some text" only if it exactly matches the complete
67
+ # innerHTML of the specified element:
68
+ # wait_for_text "some text", :element => "container"
69
+ #
70
+ def wait_for_text(pattern, options={})
71
+ builder = JavascriptExpressionBuilder.new
72
+ builder.find_text(pattern, options).append("text_match == true;")
73
+ wait_for_condition builder.script, options[:timeout_in_seconds]
74
+ end
75
+
76
+ # Wait for some text to NOT be present (the wait happens in the browser).
77
+ #
78
+ # See wait_for_text for usage details.
79
+ def wait_for_no_text(pattern, options={})
80
+ builder = JavascriptExpressionBuilder.new
81
+ builder.find_text(pattern, options).append("text_match == false;")
82
+ wait_for_condition builder.script, options[:timeout_in_seconds]
83
+ end
84
+
85
+ # Wait for a field to get a specific value (the wait happens in the browser).
86
+ def wait_for_field_value(locator, expected_value, options={})
87
+ builder = JavascriptExpressionBuilder.new
88
+ builder.find_element(locator).element_value_is(expected_value)
89
+ wait_for_condition builder.script, options[:timeout_in_seconds]
90
+ end
91
+
92
+ # Wait for a field to not have a specific value (the wait happens in the browser).
93
+ def wait_for_no_field_value(locator, expected_value, options={})
94
+ builder = JavascriptExpressionBuilder.new
95
+ builder.find_element(locator).element_value_is_not(expected_value)
96
+ wait_for_condition builder.script, options[:timeout_in_seconds]
97
+ end
98
+
99
+ # Wait for something to be visible (the wait happens in the browser).
100
+ def wait_for_visible(locator, options={})
101
+ builder = JavascriptExpressionBuilder.new
102
+ wait_for_condition builder.visible(locator).script, options[:timeout_in_seconds]
103
+ end
104
+
105
+ # Wait for something to not be visible (the wait happens in the browser).
106
+ def wait_for_not_visible(locator, options={})
107
+ builder = JavascriptExpressionBuilder.new
108
+ wait_for_condition builder.not_visible(locator).script, options[:timeout_in_seconds]
109
+ end
110
+
111
+ def active_javascript_framework(options)
112
+ options[:javascript_framework] || default_javascript_framework
113
+ end
114
+
115
+ end
116
+
117
+ end
118
+ end
@@ -0,0 +1,488 @@
1
+ module Selenium
2
+ module Client
3
+
4
+ # Provide a more idiomatic API than the generated Ruby driver.
5
+ #
6
+ # Work in progress...
7
+ module Idiomatic
8
+
9
+ # Return the text content of an HTML element (rendered text shown to
10
+ # the user). Works for any HTML element that contains text.
11
+ #
12
+ #
13
+ # This command uses either the textContent (Mozilla-like browsers)
14
+ # or the innerText (IE-like browsers) of the element, which is the
15
+ # rendered text shown to the user.
16
+ #
17
+ # * 'locator' is an Selenium element locator
18
+ #
19
+ def text(locator)
20
+ string_command "getText", [locator,]
21
+ end
22
+ alias :text_content :text
23
+
24
+ # Return the title of the current HTML page.
25
+ def title
26
+ string_command "getTitle"
27
+ end
28
+
29
+ # Returns the absolute URL of the current page.
30
+ def location
31
+ string_command "getLocation"
32
+ end
33
+
34
+ # Waits for a new page to load.
35
+ #
36
+ # Selenium constantly keeps track of new pages loading, and sets a
37
+ # "newPageLoaded" flag when it first notices a page load. Running
38
+ # any other Selenium command after turns the flag to false. Hence,
39
+ # if you want to wait for a page to load, you must wait immediately
40
+ # after a Selenium command that caused a page-load.
41
+ #
42
+ # * 'timeout_in_seconds' is a timeout in seconds, after which this
43
+ # command will return with an error
44
+ def wait_for_page(timeout_in_seconds=nil)
45
+ remote_control_command "waitForPageToLoad",
46
+ [actual_timeout_in_milliseconds(timeout_in_seconds),]
47
+ end
48
+ alias_method :wait_for_page_to_load, :wait_for_page
49
+
50
+ # Waits for a popup window to appear and load up.
51
+ #
52
+ # window_id is the JavaScript window "name" of the window that will appear (not the text of the title bar)
53
+ # timeout_in_seconds is a timeout in seconds, after which the action will return with an error
54
+ def wait_for_popup(window_id, timeout_in_seconds=nil)
55
+ remote_control_command "waitForPopUp",
56
+ [window_id, actual_timeout_in_milliseconds(timeout_in_seconds) ,]
57
+ end
58
+
59
+ # Flexible wait semantics. ait is happening browser side. Useful for testing AJAX application.
60
+ #
61
+ # * wait :wait_for => :page # will wait for a new page to load
62
+ # * wait :wait_for => :popup, :window => 'a window id' # will wait for a new popup window to appear. Also selects the popup window for you provide `:select => true`
63
+ # * wait :wait_for => :ajax # will wait for all ajax requests to be completed using semantics of default javascript framework
64
+ # * wait :wait_for => :ajax, :javascript_framework => :jquery # will wait for all ajax requests to be completed overriding default javascript framework
65
+ # * wait :wait_for => :effects # will wait for all javascript effects to be rendered using semantics of default javascript framework
66
+ # * wait :wait_for => :effects, :javascript_framework => :prototype # will wait for all javascript effects to be rendered overriding default javascript framework
67
+ # * wait :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
68
+ # * wait :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
69
+ # * wait :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
70
+ # * wait :wait_for => :text, :text => /A Regexp/ # will wait for some text to be present/appear
71
+ # * wait :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
72
+ # * wait :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
73
+ # * wait :wait_for => :no_text, :text => /A Regexp/ # will wait for the text to be not be present/disappear
74
+ # * wait :wait_for => :no_text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to not be 'some text'
75
+ # * wait :wait_for => :value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to be 'some value'
76
+ # * wait :wait_for => :no_value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to not be 'some value'
77
+ # * wait :wait_for => :visible, :element => 'a_locator' # will wait for element to be visible
78
+ # * wait :wait_for => :not_visible, :element => 'a_locator' # will wait for element to not be visible
79
+ # * wait :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
80
+ #
81
+ # Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
82
+ # is used.
83
+ def wait_for(options)
84
+ if options[:wait_for] == :page
85
+ wait_for_page options[:timeout_in_seconds]
86
+ elsif options[:wait_for] == :ajax
87
+ wait_for_ajax options
88
+ elsif options[:wait_for] == :element
89
+ wait_for_element options[:element], options
90
+ elsif options[:wait_for] == :no_element
91
+ wait_for_no_element options[:element], options
92
+ elsif options[:wait_for] == :text
93
+ wait_for_text options[:text], options
94
+ elsif options[:wait_for] == :no_text
95
+ wait_for_no_text options[:text], options
96
+ elsif options[:wait_for] == :effects
97
+ wait_for_effects options
98
+ elsif options[:wait_for] == :popup
99
+ wait_for_popup options[:window], options[:timeout_in_seconds]
100
+ select_window options[:window] if options[:select]
101
+ elsif options[:wait_for] == :value
102
+ wait_for_field_value options[:element], options[:value], options
103
+ elsif options[:wait_for] == :no_value
104
+ wait_for_no_field_value options[:element], options[:value], options
105
+ elsif options[:wait_for] == :visible
106
+ wait_for_visible options[:element], options
107
+ elsif options[:wait_for] == :not_visible
108
+ wait_for_not_visible options[:element], options
109
+ elsif options[:wait_for] == :condition
110
+ wait_for_condition options[:javascript], options[:timeout_in_seconds]
111
+ end
112
+ end
113
+
114
+ # Gets the entire text of the page.
115
+ def body_text
116
+ string_command "getBodyText"
117
+ end
118
+
119
+ # Clicks on a link, button, checkbox or radio button.
120
+ #
121
+ # 'locator' is an element locator
122
+ #
123
+ # Using 'options' you can automatically wait for an event to happen after the
124
+ # click. e.g.
125
+ #
126
+ # * click "a_locator", :wait_for => :page # will wait for a new page to load
127
+ # * click "a_locator", :wait_for => :popup, :window => 'a window id' # will wait for a new popup window to appear. Also selects the popup window for you provide `:select => true`
128
+ # * click "a_locator", :wait_for => :ajax # will wait for all ajax requests to be completed using semantics of default javascript framework
129
+ # * click "a_locator", :wait_for => :ajax, :javascript_framework => :jquery # will wait for all ajax requests to be completed overriding default javascript framework
130
+ # * click "a_locator", :wait_for => :effects # will wait for all javascript effects to be rendered using semantics of default javascript framework
131
+ # * click "a_locator", :wait_for => :effects, :javascript_framework => :prototype # will wait for all javascript effects to be rendered overriding default javascript framework
132
+ # * click "a_locator", :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
133
+ # * click "a_locator", :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
134
+ # * click "a_locator", :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
135
+ # * click "a_locator", :wait_for => :text, :text => /A Regexp/ # will wait for some text to be present/appear
136
+ # * click "a_locator", :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
137
+ # * click "a_locator", :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
138
+ # * click "a_locator", :wait_for => :no_text, :text => /A Regexp/ # will wait for the text to be not be present/disappear
139
+ # * click "a_locator", :wait_for => :no_text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to not be 'some text'
140
+ # * click "a_locator", :wait_for => :value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to be 'some value'
141
+ # * click "a_locator", :wait_for => :no_value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to not be 'some value'
142
+ # * click "a_locator", :wait_for => :visible, :element => 'a_locator' # will wait for element to be visible
143
+ # * click "a_locator", :wait_for => :not_visible, :element => 'a_locator' # will wait for element to not be visible
144
+ # * click "a_locator", :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
145
+ #
146
+ # Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
147
+ # is used.
148
+ def click(locator, options={})
149
+ remote_control_command "click", [locator,]
150
+ wait_for options
151
+ end
152
+
153
+ # Verifies that the specified text pattern appears somewhere on the rendered page shown to the user.
154
+ #
155
+ # * 'pattern' is a pattern to match with the text of the page
156
+ def text?(pattern)
157
+ boolean_command "isTextPresent", [pattern,]
158
+ end
159
+
160
+ # Verifies that the specified element is somewhere on the page.
161
+ #
162
+ # * 'locator' is an element locator
163
+ def element?(locator)
164
+ boolean_command "isElementPresent", [locator,]
165
+ end
166
+
167
+ # Determines if the specified element is visible. An
168
+ # element can be rendered invisible by setting the CSS "visibility"
169
+ # property to "hidden", or the "display" property to "none", either for the
170
+ # element itself or one if its ancestors. This method will fail if
171
+ # the element is not present.
172
+ #
173
+ # 'locator' is an element locator
174
+ def visible?(locator)
175
+ boolean_command "isVisible", [locator,]
176
+ end
177
+
178
+ # Gets the (whitespace-trimmed) value of an input field
179
+ # (or anything else with a value parameter).
180
+ # For checkbox/radio elements, the value will be "on" or "off"
181
+ # depending on whether the element is checked or not.
182
+ #
183
+ # * 'locator' is an element locator
184
+ def field(locator)
185
+ string_command "getValue", [locator,]
186
+ end
187
+
188
+ # Alias for +field+
189
+ def value(locator)
190
+ field locator
191
+ end
192
+
193
+ # Returns whether a toggle-button (checkbox/radio) is checked.
194
+ # Fails if the specified element doesn't exist or isn't a toggle-button.
195
+ #
196
+ # * 'locator' is an element locator pointing to a checkbox or radio button
197
+ def checked?(locator)
198
+ boolean_command "isChecked", [locator,]
199
+ end
200
+
201
+ # Whether an alert occurred
202
+ def alert?
203
+ boolean_command "isAlertPresent"
204
+ end
205
+
206
+ # Retrieves the message of a JavaScript alert generated during the previous action,
207
+ # or fail if there were no alerts.
208
+ #
209
+ # Getting an alert has the same effect as manually clicking OK. If an
210
+ # alert is generated but you do not consume it with getAlert, the next Selenium action
211
+ # will fail.
212
+ #
213
+ # Under Selenium, JavaScript alerts will NOT pop up a visible alert
214
+ # dialog.
215
+ #
216
+ # Selenium does NOT support JavaScript alerts that are generated in a
217
+ # page's onload() event handler. In this case a visible dialog WILL be
218
+ # generated and Selenium will hang until someone manually clicks OK.
219
+ #
220
+ def alert
221
+ string_command "getAlert"
222
+ end
223
+
224
+ # Whether a confirmation has been auto-acknoledged (i.e. confirm() been called)
225
+ def confirmation?
226
+ boolean_command "isConfirmationPresent"
227
+ end
228
+
229
+ # Retrieves the message of a JavaScript confirmation dialog generated during
230
+ # the previous action.
231
+ #
232
+ # By default, the confirm function will return true, having the same effect
233
+ # as manually clicking OK. This can be changed by prior execution of the
234
+ # chooseCancelOnNextConfirmation command.
235
+ #
236
+ # If an confirmation is generated but you do not consume it with getConfirmation,
237
+ # the next Selenium action will fail.
238
+ #
239
+ # NOTE: under Selenium, JavaScript confirmations will NOT pop up a visible
240
+ # dialog.
241
+ #
242
+ # NOTE: Selenium does NOT support JavaScript confirmations that are
243
+ # generated in a page's onload() event handler. In this case a visible
244
+ # dialog WILL be generated and Selenium will hang until you manually click
245
+ # OK.
246
+ def confirmation
247
+ string_command "getConfirmation"
248
+ end
249
+
250
+ # Whether a prompt occurred
251
+ def prompt?
252
+ boolean_command "isPromptPresent"
253
+ end
254
+
255
+ # Retrieves the message of a JavaScript question prompt dialog generated during
256
+ # the previous action.
257
+ #
258
+ # Successful handling of the prompt requires prior execution of the
259
+ # answerOnNextPrompt command. If a prompt is generated but you
260
+ # do not get/verify it, the next Selenium action will fail.
261
+ #
262
+ # NOTE: under Selenium, JavaScript prompts will NOT pop up a visible
263
+ # dialog.
264
+ #
265
+ # NOTE: Selenium does NOT support JavaScript prompts that are generated in a
266
+ # page's onload() event handler. In this case a visible dialog WILL be
267
+ # generated and Selenium will hang until someone manually clicks OK.
268
+ def prompt
269
+ string_command "getPrompt"
270
+ end
271
+
272
+ # Returns the result of evaluating the specified JavaScript snippet whithin the browser.
273
+ # The snippet may have multiple lines, but only the result of the last line will be returned.
274
+ #
275
+ # Note that, by default, the snippet will run in the context of the "selenium"
276
+ # object itself, so <tt>this</tt> will refer to the Selenium object. Use <tt>window</tt> to
277
+ # refer to the window of your application, e.g. <tt>window.document.getElementById('foo')</tt>
278
+ # If you need to use
279
+ # a locator to refer to a single element in your application page, you can
280
+ # use <tt>this.browserbot.findElement("id=foo")</tt> where "id=foo" is your locator.
281
+ #
282
+ # * 'script' is the JavaScript snippet to run
283
+ def js_eval(script)
284
+ string_command "getEval", [script,]
285
+ end
286
+
287
+ # Set the Remote Control timeout (as opposed to the client side driver timeout).
288
+ # This timout specifies the amount of time that Selenium Core will wait for actions to complete.
289
+ #
290
+ # The default timeout is 30 seconds.
291
+ # 'timeout' is a timeout in seconds, after which the action will return with an error
292
+ #
293
+ # Actions that require waiting include "open" and the "waitFor*" actions.
294
+ def remote_control_timeout_in_seconds=(timeout_in_seconds)
295
+ remote_control_command "setTimeout", [actual_timeout_in_milliseconds(timeout_in_seconds),]
296
+ end
297
+
298
+ # Returns the text from a cell of a table. The cellAddress syntax
299
+ # tableLocator.row.column, where row and column start at 0.
300
+ #
301
+ # * 'tableCellAddress' is a cell address, e.g. "foo.1.4"
302
+ def table_cell_text(tableCellAddress)
303
+ string_command "getTable", [tableCellAddress,]
304
+ end
305
+
306
+ # Runs the specified JavaScript snippet repeatedly until it evaluates to "true".
307
+ # The snippet may have multiple lines, but only the result of the last line
308
+ # will be considered.
309
+ #
310
+ # Note that, by default, the snippet will be run in the runner's test window, not in the window
311
+ # of your application. To get the window of your application, you can use
312
+ # the JavaScript snippet <tt>selenium.browserbot.getCurrentWindow()</tt>, and then
313
+ # run your JavaScript in there
314
+ #
315
+ #
316
+ # * 'script' is the JavaScript snippet to run
317
+ # * 'timeout_in_seconds' is a timeout in seconds, after which this command will return with an error
318
+ def wait_for_condition(script, timeout_in_seconds = nil)
319
+ remote_control_command "waitForCondition",
320
+ [script, actual_timeout_in_milliseconds(timeout_in_seconds),]
321
+ end
322
+
323
+ # Simulates the user clicking the "back" button on their browser.
324
+ # Using 'options' you can automatically wait for an event to happen after the
325
+ # click. e.g.
326
+ #
327
+ # * go_back :wait_for => :page # will wait for a new page to load
328
+ # * go_back :wait_for => :popup, :window => 'a window id' # will wait for a new popup window to appear. Also selects the popup window for you provide `:select => true`
329
+ # * go_back :wait_for => :ajax # will wait for all ajax requests to be completed using semantics of default javascript framework
330
+ # * go_back :wait_for => :ajax, :javascript_framework => :jquery # will wait for all ajax requests to be completed overriding default javascript framework
331
+ # * go_back :wait_for => :effects # will wait for all javascript effects to be rendered using semantics of default javascript framework
332
+ # * go_back :wait_for => :effects, :javascript_framework => :prototype # will wait for all javascript effects to be rendered overriding default javascript framework
333
+ # * go_back :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
334
+ # * go_back :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
335
+ # * go_back :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
336
+ # * go_back "a_locator", :wait_for => :text, :text => /A Regexp/ # will wait for some text to be present/appear
337
+ # * go_back :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
338
+ # * go_back :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
339
+ # * go_back "a_locator", :wait_for => :no_text, :text => /A Regexp/ # will wait for the text to be not be present/disappear
340
+ # * go_back :wait_for => :no_text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to not be 'some text'
341
+ # * go_back :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
342
+ # * go_back :wait_for => :value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to be 'some value'
343
+ # * go_back :wait_for => :visible, :element => 'a_locator' # will wait for element to be visible
344
+ # * go_back :wait_for => :not_visible, :element => 'a_locator' # will wait for element to not be visible
345
+ # * go_back :wait_for => :no_value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to not be 'some value'
346
+ #
347
+ # Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
348
+ # is used.
349
+ def go_back(options={})
350
+ remote_control_command "goBack"
351
+ wait_for options
352
+ end
353
+
354
+ # Return all cookies for the current page under test.
355
+ def cookies
356
+ string_command "getCookie"
357
+ end
358
+
359
+ # Returns the value of the cookie with the specified name, or throws an error if the cookie is not present.
360
+ #
361
+ # 'name' is the name of the cookie
362
+ def cookie(name)
363
+ string_command "getCookieByName", [name,]
364
+ end
365
+
366
+ # Returns true if a cookie with the specified name is present, or false otherwise.
367
+ #
368
+ # 'name' is the name of the cookie
369
+ def cookie?(name)
370
+ boolean_command "isCookiePresent", [name,]
371
+ end
372
+
373
+ # Create a new cookie whose path and domain are same with those of current page
374
+ # under test, unless you specified a path for this cookie explicitly.
375
+ #
376
+ # 'nameValuePair' is name and value of the cookie in a format "name=value"
377
+ # 'optionsString' is options for the cookie. Currently supported options include 'path', 'max_age' and 'domain'.
378
+ # the optionsString's format is "path=/path/, max_age=60, domain=.foo.com". The order of options are irrelevant, the unit of the value of 'max_age' is second. Note that specifying a domain that isn't a subset of the current domain will usually fail.
379
+ def create_cookie(name_value_pair, options="")
380
+ if options.kind_of? Hash
381
+ options = options.keys.collect {|key| "#{key}=#{options[key]}" }.sort.join(", ")
382
+ end
383
+ remote_control_command "createCookie", [name_value_pair,options,]
384
+ end
385
+
386
+ # Delete a named cookie with specified path and domain. Be careful; to delete a cookie, you
387
+ # need to delete it using the exact same path and domain that were used to create the cookie.
388
+ # If the path is wrong, or the domain is wrong, the cookie simply won't be deleted. Also
389
+ # note that specifying a domain that isn't a subset of the current domain will usually fail.
390
+ #
391
+ # Since there's no way to discover at runtime the original path and domain of a given cookie,
392
+ # we've added an option called 'recurse' to try all sub-domains of the current domain with
393
+ # all paths that are a subset of the current path. Beware; this option can be slow. In
394
+ # big-O notation, it operates in O(n*m) time, where n is the number of dots in the domain
395
+ # name and m is the number of slashes in the path.
396
+ #
397
+ # 'name' is the name of the cookie to be deleted
398
+ # 'optionsString' is options for the cookie. Currently supported options include 'path', 'domain' and 'recurse.' The optionsString's format is "path=/path/, domain=.foo.com, recurse=true". The order of options are irrelevant. Note that specifying a domain that isn't a subset of the current domain will usually fail.
399
+ def delete_cookie(name, options="")
400
+ if options.kind_of? Hash
401
+ ordered_keys = options.keys.sort {|a,b| a.to_s <=> b.to_s }
402
+ options = ordered_keys.collect {|key| "#{key}=#{options[key]}" }.join(", ")
403
+ end
404
+ remote_control_command "deleteCookie", [name,options,]
405
+ end
406
+
407
+ # Returns the IDs of all windows that the browser knows about.
408
+ def all_window_ids
409
+ string_array_command "getAllWindowIds"
410
+ end
411
+
412
+
413
+ # Returns the names of all windows that the browser knows about.
414
+ def all_window_names
415
+ string_array_command "getAllWindowNames"
416
+ end
417
+
418
+
419
+ # Returns the titles of all windows that the browser knows about.
420
+ def all_window_titles
421
+ string_array_command "getAllWindowTitles"
422
+ end
423
+
424
+ # Returns a string representation of the network traffic seen by the
425
+ # browser, including headers, AJAX requests, status codes, and timings.
426
+ # When this function is called, the traffic log is cleared, so the
427
+ # returned content is only the traffic seen since the last call.
428
+ #
429
+ # The network traffic is returned in the format it was requested. Valid
430
+ # values are: :json, :xml, or :plain.
431
+ #
432
+ # Warning: For browser_network_traffic to work you need to start your
433
+ # browser session with the option "captureNetworkTraffic=true", which
434
+ # will force ALL traffic to go to the Remote Control proxy even for
435
+ # more efficient browser modes like `*firefox` and `*safari`.
436
+ def browser_network_traffic(format = :plain)
437
+ raise "format must be :plain, :json, or :xml" \
438
+ unless [:plain, :json, :xml].include?(format)
439
+
440
+ remote_control_command "captureNetworkTraffic", [format.to_s]
441
+ end
442
+
443
+ # Allows choice of a specific XPath libraries for Xpath evualuation
444
+ # in the browser (e.g. to resolve XPath locators).
445
+ #
446
+ # `library_name' can be:
447
+ # * :ajaxslt : Google's library
448
+ # * :javascript-xpath : Cybozu Labs' faster library
449
+ # * :default : Selenium default library.
450
+ def browser_xpath_library=(library_name)
451
+ raise "library name must be :ajaxslt, :javascript-xpath, or :default" \
452
+ unless [:ajaxslt, :'javascript-xpath', :default].include?(library_name)
453
+ remote_control_command "useXpathLibrary", [library_name.to_s]
454
+ end
455
+
456
+ #
457
+ # Turn on/off the automatic hightlighting of the element driven or
458
+ # inspected by Selenium core. Useful when recording videos
459
+ #
460
+ def highlight_located_element=(enabled)
461
+ boolean = (true == enabled)
462
+ js_eval "selenium.browserbot.shouldHighlightLocatedElement = #{boolean}"
463
+ end
464
+
465
+ # Get execution delay in milliseconds, i.e. a pause delay following
466
+ # each selenium operation. By default, there is no such delay
467
+ # (value is 0).
468
+ def execution_delay
469
+ string_command "getSpeed"
470
+ end
471
+
472
+ # Set the execution delay in milliseconds, i.e. a pause delay following
473
+ # each selenium operation. By default, there is no such delay.
474
+ #
475
+ # Setting an execution can be useful to troubleshoot or capture videos
476
+ def execution_delay=(delay_in_milliseconds)
477
+ remote_control_command "setSpeed", [delay_in_milliseconds]
478
+ end
479
+
480
+ def actual_timeout_in_milliseconds(timeout_in_seconds)
481
+ actual_timeout = (timeout_in_seconds ||
482
+ default_timeout_in_seconds).to_i
483
+ actual_timeout * 1000
484
+ end
485
+ end
486
+
487
+ end
488
+ end