selenium-client 1.2.3 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|