selenium-client 1.2.3 → 1.2.4
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/README.markdown +41 -12
- data/lib/selenium/client/base.rb +2 -0
- data/lib/selenium/client/extensions.rb +37 -19
- data/lib/selenium/client/idiomatic.rb +97 -20
- data/lib/selenium/rspec/spec_helper.rb +1 -1
- metadata +3 -3
data/README.markdown
CHANGED
@@ -16,22 +16,35 @@ Install It
|
|
16
16
|
Features
|
17
17
|
========
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
* Backward compatible with the old-fashioned, XSL generated Selenium Ruby API.
|
20
|
+
See [the generated driver](http://selenium-client.rubyforge.org/classes/Selenium/Client/GeneratedDriver.html) to get an extensive reference.
|
21
21
|
|
22
|
-
|
22
|
+
* Idiomatic interface to the Selenium API.
|
23
23
|
See [the Idiomatic module](http://selenium-client.rubyforge.org/classes/Selenium/Client/Idiomatic.html)
|
24
24
|
for more details.
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
* Convenience methods for AJAX.
|
27
|
+
See the [Extensions](http://selenium-client.rubyforge.org/classes/Selenium/Client/Extensions.html)
|
28
|
+
for more details.
|
29
|
+
|
30
|
+
* Flexible wait semantics inline with the trigerring action. e.g.
|
31
31
|
|
32
|
-
|
32
|
+
* `click 'the_button_id', :wait_for => :page`
|
33
|
+
* `click 'the_button_id', :wait_for => :ajax`
|
34
|
+
* `click 'the_button_id', :wait_for => :element, :element => 'new_element_id'`
|
35
|
+
* `click 'the_button_id', :wait_for => :no_element, :element => 'disappearing_element_id'`
|
36
|
+
* `click 'the_button_id', :wait_for => :text, :text => 'New Text'`
|
37
|
+
* `click 'the_button_id', :wait_for => :no_text, :text => 'Disappearing Text'`
|
38
|
+
* `click 'the_button_id', :wait_for => :effects`
|
39
|
+
* `click 'the_button_id', :wait_for => :condition, :javascript => "some arbitrary javascript expression"`
|
33
40
|
|
34
|
-
|
41
|
+
Check out the `click`, `go_back` and `wait_for` methods of the [Idiomatic Module](http://selenium-client.rubyforge.org/classes/Selenium/Client/Idiomatic.html)
|
42
|
+
|
43
|
+
* Leveraging latest innovations in Selenium Remote Control (screenshots, log captures, ...)
|
44
|
+
|
45
|
+
* Robust Rake task to start/stop the Selenium Remote Control server. More details in the next section.
|
46
|
+
|
47
|
+
* State-of-the-art reporting for RSpec.
|
35
48
|
|
36
49
|
Plain API
|
37
50
|
=========
|
@@ -131,8 +144,9 @@ Writing Tests
|
|
131
144
|
selenium_driver.start_new_browser_session
|
132
145
|
end
|
133
146
|
|
134
|
-
|
135
|
-
|
147
|
+
# The system capture need to happen BEFORE closing the Selenium session
|
148
|
+
config.append_after(:each) do
|
149
|
+
@selenium_driver.close_current_browser_session
|
136
150
|
end
|
137
151
|
|
138
152
|
it "can find Selenium" do
|
@@ -202,6 +216,21 @@ Grid](http://selenium-grid.openqa.org))
|
|
202
216
|
|
203
217
|
You can then get cool reports like [this one](http://ph7spot.com/examples/selenium_rspec_report.html)
|
204
218
|
|
219
|
+
Contribute and Join the Fun!
|
220
|
+
============================
|
221
|
+
|
222
|
+
We welcome new features, add-ons, bug fixes, example, documentation, etc. Make the gem work the way you
|
223
|
+
envision!
|
224
|
+
|
225
|
+
* I recommend cloning the selenium-client [reference repository](http://github.com/ph7/selenium-client/tree/master)
|
226
|
+
I you are more of a SVN guy, the same code also lives at [OpenQA](http://svn.openqa.org/svn/selenium-rc/trunk/clients/ruby)
|
227
|
+
|
228
|
+
* You can also check out the [RubyForge page](http://rubyforge.org/projects/selenium-client) and the [RDoc](http://selenium-client.rubyforge.org)
|
229
|
+
|
230
|
+
* We also have a [continuous integration server](http://xserve.openqa.org:8080/view/Ruby%20Client)
|
231
|
+
|
205
232
|
|
233
|
+
|
234
|
+
|
206
235
|
|
207
236
|
|
data/lib/selenium/client/base.rb
CHANGED
@@ -9,6 +9,8 @@ module Selenium
|
|
9
9
|
include Selenium::Client::GeneratedDriver
|
10
10
|
include Selenium::Client::Extensions
|
11
11
|
include Selenium::Client::Idiomatic
|
12
|
+
|
13
|
+
attr_reader :browser_string
|
12
14
|
|
13
15
|
def initialize(server_host, server_port, browser_string, browser_url, timeout_in_seconds=300)
|
14
16
|
@server_host = server_host
|
@@ -4,52 +4,69 @@ module Selenium
|
|
4
4
|
# Convenience methods not explicitely part of the protocol
|
5
5
|
module Extensions
|
6
6
|
|
7
|
-
# These for all Ajax request to finish (Only works if you are using prototype)
|
7
|
+
# These for all Ajax request to finish (Only works if you are using prototype, the wait in happenning browser side)
|
8
8
|
#
|
9
9
|
# See http://davidvollbracht.com/2008/6/4/30-days-of-tech-day-3-waitforajax for
|
10
10
|
# more background.
|
11
|
-
def wait_for_ajax(
|
12
|
-
selenium.wait_for_condition "selenium.browserbot.getCurrentWindow().Ajax.activeRequestCount == 0",
|
13
|
-
timeout || default_timeout_in_seconds
|
11
|
+
def wait_for_ajax(timeout_in_seconds=nil)
|
12
|
+
selenium.wait_for_condition "selenium.browserbot.getCurrentWindow().Ajax.activeRequestCount == 0", timeout_in_seconds
|
14
13
|
end
|
15
14
|
|
16
|
-
# Wait for all Prototype effects to be processed
|
15
|
+
# Wait for all Prototype effects to be processed (the wait in happenning browser side).
|
17
16
|
#
|
18
17
|
# Credits to http://github.com/brynary/webrat/tree/master
|
19
|
-
def wait_for_effects(
|
20
|
-
selenium.wait_for_condition "window.Effect.Queue.size() == 0",
|
18
|
+
def wait_for_effects(timeout_in_seconds=nil)
|
19
|
+
selenium.wait_for_condition "window.Effect.Queue.size() == 0", timeout_in_seconds
|
21
20
|
end
|
22
21
|
|
23
|
-
|
22
|
+
# Wait for an element to be present (the wait in happenning browser side).
|
23
|
+
def wait_for_element(locator, timeout_in_seconds=nil)
|
24
24
|
script = <<-EOS
|
25
25
|
var element;
|
26
26
|
try {
|
27
|
-
element = selenium.browserbot.findElement('#{
|
27
|
+
element = selenium.browserbot.findElement('#{locator}');
|
28
28
|
} catch(e) {
|
29
29
|
element = null;
|
30
30
|
}
|
31
31
|
element != null
|
32
32
|
EOS
|
33
33
|
|
34
|
-
wait_for_condition script,
|
34
|
+
wait_for_condition script, timeout_in_seconds
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
# Wait for an element to NOT be present (the wait in happenning browser side).
|
38
|
+
def wait_for_no_element(locator, timeout_in_seconds=nil)
|
39
|
+
script = <<-EOS
|
40
|
+
var element;
|
41
|
+
try {
|
42
|
+
element = selenium.browserbot.findElement('#{locator}');
|
43
|
+
} catch(e) {
|
44
|
+
element = null;
|
45
|
+
}
|
46
|
+
element == null
|
47
|
+
EOS
|
48
|
+
|
49
|
+
wait_for_condition script, timeout_in_seconds
|
50
|
+
end
|
51
|
+
|
52
|
+
# Wait for some text to be present (the wait in happenning browser side).
|
53
|
+
def wait_for_text(locator, text, timeout_in_seconds=nil)
|
38
54
|
script = "var element;
|
39
55
|
try {
|
40
|
-
element = selenium.browserbot.findElement('#{
|
56
|
+
element = selenium.browserbot.findElement('#{locator}');
|
41
57
|
} catch(e) {
|
42
58
|
element = null;
|
43
59
|
}
|
44
60
|
element != null && element.innerHTML == '#{text}'"
|
45
61
|
|
46
|
-
wait_for_condition script,
|
62
|
+
wait_for_condition script, timeout_in_seconds
|
47
63
|
end
|
48
64
|
|
49
|
-
|
65
|
+
# Wait for some text to NOT be present (the wait in happenning browser side).
|
66
|
+
def wait_for_no_text(locator, original_text, timeout_in_seconds=nil)
|
50
67
|
script = "var element;
|
51
68
|
try {
|
52
|
-
element = selenium.browserbot.findElement('#{
|
69
|
+
element = selenium.browserbot.findElement('#{locator}');
|
53
70
|
} catch(e) {
|
54
71
|
element = null;
|
55
72
|
}
|
@@ -58,16 +75,17 @@ module Selenium
|
|
58
75
|
wait_for_condition script, time
|
59
76
|
end
|
60
77
|
|
61
|
-
|
78
|
+
# Wait for a field to get a specific value (the wait in happenning browser side).
|
79
|
+
def wait_for_field_value(locator, expected_value, timeout_in_seconds=nil)
|
62
80
|
script = "var element;
|
63
81
|
try {
|
64
|
-
element = selenium.browserbot.findElement('#{
|
82
|
+
element = selenium.browserbot.findElement('#{locator}');
|
65
83
|
} catch(e) {
|
66
84
|
element = null;
|
67
85
|
}
|
68
|
-
element != null && element.value == '#{
|
86
|
+
element != null && element.value == '#{expected_value}'"
|
69
87
|
|
70
|
-
wait_for_condition script,
|
88
|
+
wait_for_condition script, timeout_in_seconds
|
71
89
|
end
|
72
90
|
|
73
91
|
end
|
@@ -14,7 +14,7 @@ module Selenium
|
|
14
14
|
# or the innerText (IE-like browsers) of the element, which is the
|
15
15
|
# rendered text shown to the user.
|
16
16
|
#
|
17
|
-
# 'locator' is an Selenium element locator
|
17
|
+
# * 'locator' is an Selenium element locator
|
18
18
|
def text_content(locator)
|
19
19
|
string_command"getText", [locator,]
|
20
20
|
end
|
@@ -37,44 +37,84 @@ module Selenium
|
|
37
37
|
# if you want to wait for a page to load, you must wait immediately
|
38
38
|
# after a Selenium command that caused a page-load.
|
39
39
|
#
|
40
|
-
# 'timeout_in_seconds' is a timeout in seconds, after which this
|
41
|
-
#
|
40
|
+
# * 'timeout_in_seconds' is a timeout in seconds, after which this
|
41
|
+
# command will return with an error
|
42
42
|
def wait_for_page(timeout_in_seconds=nil)
|
43
43
|
actual_timeout = timeout_in_seconds || default_timeout_in_seconds
|
44
44
|
remote_control_command "waitForPageToLoad", [actual_timeout * 1000,]
|
45
45
|
end
|
46
46
|
|
47
|
+
# Flexible wait semantics. ait is happening browser side. Useful for testing AJAX application.
|
48
|
+
#
|
49
|
+
# * wait :wait_for => :page # will wait for a new page to load
|
50
|
+
# * wait :wait_for => :ajax # will wait for all ajax requests to be completed (Prototype only)
|
51
|
+
# * wait :wait_for => :effects # will wait for all Prototype effects to be rendered
|
52
|
+
# * wait :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
53
|
+
# * wait :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
54
|
+
# * wait :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
|
55
|
+
# * wait :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
|
56
|
+
# * wait :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
|
57
|
+
#
|
58
|
+
# Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
|
59
|
+
# is used.
|
60
|
+
def wait_for(options)
|
61
|
+
if options[:wait_for] == :page
|
62
|
+
wait_for_page options[:timeout_in_seconds]
|
63
|
+
elsif options[:wait_for] == :ajax
|
64
|
+
wait_for_ajax options[:timeout_in_seconds]
|
65
|
+
elsif options[:wait_for] == :element
|
66
|
+
wait_for_element options[:element], options[:timeout_in_seconds]
|
67
|
+
elsif options[:wait_for] == :no_element
|
68
|
+
wait_for_no_element options[:element], options[:timeout_in_seconds]
|
69
|
+
elsif options[:wait_for] == :text
|
70
|
+
wait_for_text options[:text], options[:timeout_in_seconds]
|
71
|
+
elsif options[:wait_for] == :no_text
|
72
|
+
wait_for_no_text options[:text], options[:timeout_in_seconds]
|
73
|
+
elsif options[:wait_for] == :effects
|
74
|
+
wait_for_effects options[:timeout_in_seconds]
|
75
|
+
elsif options[:wait_for] == :condition
|
76
|
+
wait_for_condition options[:javascript], options[:timeout_in_seconds]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
47
80
|
# Gets the entire text of the page.
|
48
81
|
def body_text
|
49
82
|
string_command"getBodyText"
|
50
83
|
end
|
51
84
|
|
52
|
-
# Clicks on a link, button, checkbox or radio button.
|
53
|
-
# causes a new page to load (like a link usually does), call
|
54
|
-
# waitForPageToLoad.
|
85
|
+
# Clicks on a link, button, checkbox or radio button.
|
55
86
|
#
|
56
87
|
# 'locator' is an element locator
|
88
|
+
#
|
89
|
+
# Using 'options' you can automatically wait for an event to happen after the
|
90
|
+
# click. e.g.
|
91
|
+
#
|
92
|
+
# * click 'some_id', :wait_for => :page # will wait for a new page to load
|
93
|
+
# * click 'some_id', :wait_for => :ajax # will wait for all ajax requests to be completed (Prototype only)
|
94
|
+
# * click 'some_id', :wait_for => :effects # will wait for all Prototype effects to be rendered
|
95
|
+
# * click 'some_id', :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
96
|
+
# * click 'some_id', :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
97
|
+
# * click :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
|
98
|
+
# * click :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
|
99
|
+
# * click 'some_id', :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
|
100
|
+
#
|
101
|
+
# Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
|
102
|
+
# is used.
|
57
103
|
def click(locator, options={})
|
58
104
|
remote_control_command("click", [locator,])
|
59
|
-
|
60
|
-
wait_for_page options[:timeout_in_seconds]
|
61
|
-
elsif options[:wait_for] == :ajax
|
62
|
-
wait_for_ajax options[:timeout_in_seconds]
|
63
|
-
elsif options[:wait_for] == :effects
|
64
|
-
wait_for_effects options[:timeout_in_seconds]
|
65
|
-
end
|
105
|
+
wait_for options
|
66
106
|
end
|
67
107
|
|
68
108
|
# Verifies that the specified text pattern appears somewhere on the rendered page shown to the user.
|
69
109
|
#
|
70
|
-
# 'pattern' is a pattern to match with the text of the page
|
110
|
+
# * 'pattern' is a pattern to match with the text of the page
|
71
111
|
def text?(pattern)
|
72
112
|
boolean_command "isTextPresent", [pattern,]
|
73
113
|
end
|
74
114
|
|
75
115
|
# Verifies that the specified element is somewhere on the page.
|
76
116
|
#
|
77
|
-
# 'locator' is an element locator
|
117
|
+
# * 'locator' is an element locator
|
78
118
|
def element?(locator)
|
79
119
|
boolean_command "isElementPresent", [locator,]
|
80
120
|
end
|
@@ -84,7 +124,7 @@ module Selenium
|
|
84
124
|
# For checkbox/radio elements, the value will be "on" or "off"
|
85
125
|
# depending on whether the element is checked or not.
|
86
126
|
#
|
87
|
-
# 'locator' is an element locator
|
127
|
+
# * 'locator' is an element locator
|
88
128
|
def field(locator)
|
89
129
|
string_command "getValue", [locator,]
|
90
130
|
end
|
@@ -97,7 +137,7 @@ module Selenium
|
|
97
137
|
# Returns whether a toggle-button (checkbox/radio) is checked.
|
98
138
|
# Fails if the specified element doesn't exist or isn't a toggle-button.
|
99
139
|
#
|
100
|
-
# 'locator' is an element locator pointing to a checkbox or radio button
|
140
|
+
# * 'locator' is an element locator pointing to a checkbox or radio button
|
101
141
|
def checked?(locator)
|
102
142
|
boolean_command "isChecked", [locator,]
|
103
143
|
end
|
@@ -113,8 +153,10 @@ module Selenium
|
|
113
153
|
# Getting an alert has the same effect as manually clicking OK. If an
|
114
154
|
# alert is generated but you do not consume it with getAlert, the next Selenium action
|
115
155
|
# will fail.
|
156
|
+
#
|
116
157
|
# Under Selenium, JavaScript alerts will NOT pop up a visible alert
|
117
158
|
# dialog.
|
159
|
+
#
|
118
160
|
# Selenium does NOT support JavaScript alerts that are generated in a
|
119
161
|
# page's onload() event handler. In this case a visible dialog WILL be
|
120
162
|
# generated and Selenium will hang until someone manually clicks OK.
|
@@ -181,7 +223,7 @@ module Selenium
|
|
181
223
|
# a locator to refer to a single element in your application page, you can
|
182
224
|
# use <tt>this.browserbot.findElement("id=foo")</tt> where "id=foo" is your locator.
|
183
225
|
#
|
184
|
-
# 'script' is the JavaScript snippet to run
|
226
|
+
# * 'script' is the JavaScript snippet to run
|
185
227
|
def js_eval(script)
|
186
228
|
string_command"getEval", [script,]
|
187
229
|
end
|
@@ -200,12 +242,47 @@ module Selenium
|
|
200
242
|
# Returns the text from a cell of a table. The cellAddress syntax
|
201
243
|
# tableLocator.row.column, where row and column start at 0.
|
202
244
|
#
|
203
|
-
# 'tableCellAddress' is a cell address, e.g. "foo.1.4"
|
245
|
+
# * 'tableCellAddress' is a cell address, e.g. "foo.1.4"
|
204
246
|
def table_cell_text(tableCellAddress)
|
205
247
|
string_command "getTable", [tableCellAddress,]
|
206
248
|
end
|
207
249
|
|
208
|
-
#
|
250
|
+
# Runs the specified JavaScript snippet repeatedly until it evaluates to "true".
|
251
|
+
# The snippet may have multiple lines, but only the result of the last line
|
252
|
+
# will be considered.
|
253
|
+
#
|
254
|
+
# Note that, by default, the snippet will be run in the runner's test window, not in the window
|
255
|
+
# of your application. To get the window of your application, you can use
|
256
|
+
# the JavaScript snippet <tt>selenium.browserbot.getCurrentWindow()</tt>, and then
|
257
|
+
# run your JavaScript in there
|
258
|
+
#
|
259
|
+
#
|
260
|
+
# * 'script' is the JavaScript snippet to run
|
261
|
+
# * 'timeout_in_seconds' is a timeout in seconds, after which this command will return with an error
|
262
|
+
def wait_for_condition(script, timeout_in_seconds = nil)
|
263
|
+
remote_control_command "waitForCondition", [script, (timeout_in_seconds || default_timeout_in_seconds) * 1000,]
|
264
|
+
end
|
265
|
+
|
266
|
+
# Simulates the user clicking the "back" button on their browser.
|
267
|
+
# Using 'options' you can automatically wait for an event to happen after the
|
268
|
+
# click. e.g.
|
269
|
+
#
|
270
|
+
# * go_back :wait_for => :page # will wait for a new page to load
|
271
|
+
# * go_back :wait_for => :ajax # will wait for all ajax requests to be completed (Prototype only)
|
272
|
+
# * go_back :wait_for => :effects # will wait for all Prototype effects to be rendered
|
273
|
+
# * go_back :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
274
|
+
# * go_back :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
275
|
+
# * go_back :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
|
276
|
+
# * go_back :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
|
277
|
+
# * go_back :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
|
278
|
+
#
|
279
|
+
# Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
|
280
|
+
# is used.
|
281
|
+
def go_back(options={})
|
282
|
+
remote_control_command "goBack"
|
283
|
+
wait_for options
|
284
|
+
end
|
285
|
+
|
209
286
|
end
|
210
287
|
|
211
288
|
end
|
@@ -7,7 +7,7 @@ require File.expand_path(File.dirname(__FILE__) + "/reporting/selenium_test_repo
|
|
7
7
|
|
8
8
|
Spec::Runner.configure do |config|
|
9
9
|
|
10
|
-
config.
|
10
|
+
config.prepend_after(:each) do
|
11
11
|
begin
|
12
12
|
Selenium::RSpec::SeleniumTestReportFormatter.capture_system_state(selenium_driver, self) if execution_error
|
13
13
|
if selenium_driver.session_started?
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selenium-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OpenQA
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-09-
|
12
|
+
date: 2008-09-30 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -72,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements: []
|
73
73
|
|
74
74
|
rubyforge_project: selenium-client
|
75
|
-
rubygems_version: 1.
|
75
|
+
rubygems_version: 1.2.0
|
76
76
|
signing_key:
|
77
77
|
specification_version: 2
|
78
78
|
summary: Official Ruby Client for Selenium RC.
|