selenium-client 1.2.12 → 1.2.13
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +22 -5
- data/examples/rspec/google_spec.rb +1 -1
- data/examples/script/google.rb +1 -1
- data/examples/testunit/google_test.rb +1 -1
- data/lib/selenium/client.rb +2 -1
- data/lib/selenium/client/extensions.rb +62 -85
- data/lib/selenium/client/idiomatic.rb +6 -0
- data/lib/selenium/client/javascript_expression_builder.rb +108 -0
- data/lib/selenium/client/protocol.rb +2 -0
- metadata +3 -3
- data/lib/selenium/client/generated_driver.rb +0 -1711
data/README.markdown
CHANGED
@@ -38,8 +38,10 @@ Features
|
|
38
38
|
* `click 'the_button_id', :wait_for => :element, :element => 'new_element_id'`
|
39
39
|
* `click 'the_button_id', :wait_for => :no_element, :element => 'disappearing_element_id'`
|
40
40
|
* `click 'the_button_id', :wait_for => :text, :text => 'New Text'`
|
41
|
+
* `click 'the_button_id', :wait_for => :text, :text => /A Regexp/`
|
41
42
|
* `click 'the_button_id', :wait_for => :text, :element => 'notification_box', :text => 'New Text'`
|
42
43
|
* `click 'the_button_id', :wait_for => :no_text, :text => 'Disappearing Text'`
|
44
|
+
* `click 'the_button_id', :wait_for => :no_text, :text => /A Regexp/`
|
43
45
|
* `click 'the_button_id', :wait_for => :no_text, :element => 'notification_box', :text => 'Disappearing Text'`
|
44
46
|
* `click 'the_button_id', :wait_for => :effects`
|
45
47
|
* `click 'the_button_id', :wait_for => :value, :element => 'a_locator', :value => 'some value'`
|
@@ -78,7 +80,7 @@ Plain API
|
|
78
80
|
# Sample Ruby script using the Selenium client API
|
79
81
|
#
|
80
82
|
require "rubygems"
|
81
|
-
gem "selenium-client", ">=1.2.
|
83
|
+
gem "selenium-client", ">=1.2.13"
|
82
84
|
require "selenium/client"
|
83
85
|
|
84
86
|
begin
|
@@ -111,7 +113,7 @@ Writing Tests
|
|
111
113
|
#
|
112
114
|
require "test/unit"
|
113
115
|
require "rubygems"
|
114
|
-
gem "selenium-client", ">=1.2.
|
116
|
+
gem "selenium-client", ">=1.2.13"
|
115
117
|
require "selenium/client"
|
116
118
|
|
117
119
|
class ExampleTest < Test::Unit::TestCase
|
@@ -149,7 +151,7 @@ Writing Tests
|
|
149
151
|
|
150
152
|
require 'rubygems'
|
151
153
|
gem "rspec", "=1.1.12"
|
152
|
-
gem "selenium-client", ">=1.2.
|
154
|
+
gem "selenium-client", ">=1.2.13"
|
153
155
|
require "selenium/client"
|
154
156
|
require "selenium/rspec/spec_helper"
|
155
157
|
|
@@ -260,14 +262,29 @@ Contribute and Join the Fun!
|
|
260
262
|
envision!
|
261
263
|
|
262
264
|
* I recommend cloning the selenium-client [reference repository](http://github.com/ph7/selenium-client/tree/master)
|
263
|
-
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)
|
264
265
|
|
265
266
|
* You can also check out the [RubyForge page](http://rubyforge.org/projects/selenium-client) and the [RDoc](http://selenium-client.rubyforge.org)
|
266
267
|
|
267
268
|
* We also have a [continuous integration server](http://xserve.openqa.org:8080/view/Ruby%20Client)
|
268
269
|
|
270
|
+
* Stories live in [Pivotal Tracker](https://www.pivotaltracker.com/projects/6280)
|
269
271
|
|
272
|
+
Core Team
|
273
|
+
=========
|
274
|
+
|
275
|
+
* Philippe Hanrigou (`ph7`): Current Maintainer and main contributor
|
276
|
+
* Aslak Hellesoy and Darren Hobbs : Original version of the Selenium Ruby driver
|
277
|
+
|
278
|
+
Contributors
|
279
|
+
============
|
270
280
|
|
281
|
+
* Aaron Tinio (`aptinio`):
|
282
|
+
- Patch for more robust Selenium RC shutdown
|
283
|
+
- Patch to support locator including single quotes in `wait_for_...` methods
|
284
|
+
|
285
|
+
* Rick Lee-Morlang (`rleemorlang`):
|
286
|
+
- Patch for incremental calls to `wait_for_text`
|
287
|
+
- Regex support in `wait_for_text`
|
288
|
+
|
271
289
|
|
272
290
|
|
273
|
-
|
data/examples/script/google.rb
CHANGED
data/lib/selenium/client.rb
CHANGED
@@ -13,8 +13,9 @@ require File.expand_path(File.dirname(__FILE__) + '/command_error')
|
|
13
13
|
require File.expand_path(File.dirname(__FILE__) + '/protocol_error')
|
14
14
|
require File.expand_path(File.dirname(__FILE__) + '/client/protocol')
|
15
15
|
require File.expand_path(File.dirname(__FILE__) + '/client/generated_driver')
|
16
|
-
require File.expand_path(File.dirname(__FILE__) + '/client/
|
16
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/javascript_expression_builder')
|
17
17
|
require File.expand_path(File.dirname(__FILE__) + '/client/javascript_frameworks/prototype')
|
18
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/javascript_frameworks/jquery')
|
18
19
|
require File.expand_path(File.dirname(__FILE__) + '/client/extensions')
|
19
20
|
require File.expand_path(File.dirname(__FILE__) + '/client/idiomatic')
|
20
21
|
require File.expand_path(File.dirname(__FILE__) + '/client/base')
|
@@ -9,8 +9,8 @@ module Selenium
|
|
9
9
|
# See http://davidvollbracht.com/2008/6/4/30-days-of-tech-day-3-waitforajax for
|
10
10
|
# more background.
|
11
11
|
def wait_for_ajax(options={})
|
12
|
-
|
13
|
-
wait_for_condition
|
12
|
+
builder = JavascriptExpressionBuilder.new active_javascript_framework(options)
|
13
|
+
wait_for_condition builder.no_pending_ajax_requests.script,
|
14
14
|
options[:timeout_in_seconds]
|
15
15
|
end
|
16
16
|
|
@@ -18,111 +18,88 @@ module Selenium
|
|
18
18
|
#
|
19
19
|
# Credits to http://github.com/brynary/webrat/tree/master
|
20
20
|
def wait_for_effects(options={})
|
21
|
-
|
21
|
+
builder = JavascriptExpressionBuilder.new active_javascript_framework(options)
|
22
|
+
wait_for_condition builder.no_pending_effects.script,
|
22
23
|
options[:timeout_in_seconds]
|
23
24
|
end
|
24
25
|
|
25
26
|
# Wait for an element to be present (the wait in happenning browser side).
|
26
27
|
def wait_for_element(locator, options={})
|
27
|
-
|
28
|
-
|
28
|
+
builder = JavascriptExpressionBuilder.new
|
29
|
+
builder.find_element(locator).append("element != null;")
|
30
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
29
31
|
end
|
30
32
|
|
31
33
|
# Wait for an element to NOT be present (the wait in happenning browser side).
|
32
34
|
def wait_for_no_element(locator, options={})
|
33
|
-
|
34
|
-
|
35
|
+
builder = JavascriptExpressionBuilder.new
|
36
|
+
builder.find_element(locator).append("element == null;")
|
37
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
35
38
|
end
|
36
39
|
|
37
|
-
# Wait for some text to be present (the wait
|
40
|
+
# Wait for some text to be present (the wait is happening browser side).
|
38
41
|
#
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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 in happenning browser side).
|
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
|
67
84
|
|
68
85
|
# Wait for a field to get a specific value (the wait in happenning browser side).
|
69
86
|
def wait_for_field_value(locator, expected_value, options={})
|
70
|
-
|
71
|
-
|
72
|
-
wait_for_condition script, options[:timeout_in_seconds]
|
87
|
+
builder = JavascriptExpressionBuilder.new
|
88
|
+
builder.find_element(locator).element_value_is(expected_value)
|
89
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
73
90
|
end
|
74
91
|
|
75
92
|
def wait_for_no_field_value(locator, expected_value, options={})
|
76
|
-
|
77
|
-
|
78
|
-
wait_for_condition script, options[:timeout_in_seconds]
|
79
|
-
end
|
80
|
-
|
81
|
-
def javascript_framework_for(framework_name)
|
82
|
-
case framework_name.to_sym
|
83
|
-
when :prototype
|
84
|
-
JavascriptFrameworks::Prototype
|
85
|
-
when :jquery
|
86
|
-
JavascriptFrameworks::JQuery
|
87
|
-
else
|
88
|
-
raise "Unsupported Javascript Framework: #{framework_name}"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def find_element_script(locator, return_value)
|
93
|
-
script = <<-EOS
|
94
|
-
var element;
|
95
|
-
|
96
|
-
try {
|
97
|
-
element = selenium.browserbot.findElement('#{quote_escaped(locator)}');
|
98
|
-
} catch(e) {
|
99
|
-
element = null;
|
100
|
-
}
|
101
|
-
#{return_value};
|
102
|
-
EOS
|
103
|
-
end
|
104
|
-
|
105
|
-
def find_text_script(text, return_value)
|
106
|
-
script = <<-EOS
|
107
|
-
var text;
|
108
|
-
|
109
|
-
try {
|
110
|
-
text = selenium.browserbot.getCurrentWindow().find('#{quote_escaped(text)}');
|
111
|
-
} catch(e) {
|
112
|
-
text = null;
|
113
|
-
}
|
114
|
-
#{return_value};
|
115
|
-
EOS
|
93
|
+
builder = JavascriptExpressionBuilder.new
|
94
|
+
builder.find_element(locator).element_value_is_not(expected_value)
|
95
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
116
96
|
end
|
117
97
|
|
118
|
-
def
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
def quote_escaped(a_string)
|
123
|
-
a_string.gsub(/'/, %q<\\\'>)
|
98
|
+
def active_javascript_framework(options)
|
99
|
+
options[:javascript_framework] || default_javascript_framework
|
124
100
|
end
|
125
101
|
|
126
102
|
end
|
103
|
+
|
127
104
|
end
|
128
105
|
end
|
@@ -67,8 +67,10 @@ module Selenium
|
|
67
67
|
# * wait :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
68
68
|
# * wait :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
69
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
|
70
71
|
# * wait :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
|
71
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
|
72
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'
|
73
75
|
# * wait :wait_for => :value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to be 'some value'
|
74
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'
|
@@ -124,8 +126,10 @@ module Selenium
|
|
124
126
|
# * click "a_locator", :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
125
127
|
# * click "a_locator", :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
126
128
|
# * click "a_locator", :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
|
129
|
+
# * click "a_locator", :wait_for => :text, :text => /A Regexp/ # will wait for some text to be present/appear
|
127
130
|
# * click "a_locator", :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
|
128
131
|
# * click "a_locator", :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
|
132
|
+
# * click "a_locator", :wait_for => :no_text, :text => /A Regexp/ # will wait for the text to be not be present/disappear
|
129
133
|
# * 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'
|
130
134
|
# * 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'
|
131
135
|
# * 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'
|
@@ -320,8 +324,10 @@ module Selenium
|
|
320
324
|
# * go_back :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
321
325
|
# * go_back :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
322
326
|
# * go_back :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
|
327
|
+
# * go_back "a_locator", :wait_for => :text, :text => /A Regexp/ # will wait for some text to be present/appear
|
323
328
|
# * go_back :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
|
324
329
|
# * go_back :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
|
330
|
+
# * go_back "a_locator", :wait_for => :no_text, :text => /A Regexp/ # will wait for the text to be not be present/disappear
|
325
331
|
# * 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'
|
326
332
|
# * go_back :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
|
327
333
|
# * go_back :wait_for => :value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to be 'some value'
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Selenium
|
2
|
+
module Client
|
3
|
+
|
4
|
+
class JavascriptExpressionBuilder
|
5
|
+
attr_reader :script
|
6
|
+
|
7
|
+
def initialize(javascript_framework_name=nil)
|
8
|
+
@framework = javascript_framework_for(javascript_framework_name) if javascript_framework_name
|
9
|
+
@script = ""
|
10
|
+
end
|
11
|
+
|
12
|
+
def append(text)
|
13
|
+
@script << text
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def no_pending_ajax_requests
|
18
|
+
append window_script("#{@framework.ajax_request_tracker} == 0")
|
19
|
+
end
|
20
|
+
|
21
|
+
def no_pending_effects
|
22
|
+
append window_script("Effect.Queue.size() == 0")
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_element(locator)
|
26
|
+
append <<-EOS
|
27
|
+
var element;
|
28
|
+
|
29
|
+
try {
|
30
|
+
element = selenium.browserbot.findElement('#{quote_escaped(locator)}');
|
31
|
+
} catch(e) {
|
32
|
+
element = null;
|
33
|
+
}
|
34
|
+
EOS
|
35
|
+
end
|
36
|
+
|
37
|
+
def element_value_is(expected_value)
|
38
|
+
append "(element != null && element.value == '#{quote_escaped(expected_value)}')"
|
39
|
+
end
|
40
|
+
|
41
|
+
def element_value_is_not(expected_value)
|
42
|
+
append "(element == null || element.value != '#{quote_escaped(expected_value)}')"
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_text(pattern, options)
|
46
|
+
if options[:element].nil?
|
47
|
+
find_text_in_document pattern, options
|
48
|
+
else
|
49
|
+
find_text_in_element pattern, options
|
50
|
+
end
|
51
|
+
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_text_in_document(pattern, options)
|
56
|
+
js_regexp = case pattern
|
57
|
+
when Regexp
|
58
|
+
pattern.inspect
|
59
|
+
else
|
60
|
+
/#{pattern}/.inspect
|
61
|
+
end
|
62
|
+
append <<-EOS
|
63
|
+
var text_match;
|
64
|
+
text_match = (null != selenium.browserbot.getCurrentWindow().document.body.innerHTML.match(#{js_regexp}));
|
65
|
+
EOS
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_text_in_element(pattern, options)
|
70
|
+
find_element(options[:element])
|
71
|
+
append <<-EOS
|
72
|
+
var text_match;
|
73
|
+
text_match = (element != null && #{text_match(pattern)});
|
74
|
+
EOS
|
75
|
+
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
def text_match(pattern)
|
80
|
+
case pattern
|
81
|
+
when Regexp
|
82
|
+
"null != element.innerHTML.match(#{pattern.inspect})"
|
83
|
+
else
|
84
|
+
"element.innerHTML == '#{quote_escaped(pattern)}'"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def javascript_framework_for(framework_name)
|
89
|
+
case framework_name.to_sym
|
90
|
+
when :prototype
|
91
|
+
JavascriptFrameworks::Prototype
|
92
|
+
when :jquery
|
93
|
+
JavascriptFrameworks::JQuery
|
94
|
+
else
|
95
|
+
raise "Unsupported Javascript Framework: #{framework_name}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def window_script(expression)
|
100
|
+
"selenium.browserbot.getCurrentWindow().#{expression};"
|
101
|
+
end
|
102
|
+
|
103
|
+
def quote_escaped(a_string)
|
104
|
+
a_string.gsub(/'/, %q<\\\'>)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -83,6 +83,8 @@ module Selenium
|
|
83
83
|
def http_post(data)
|
84
84
|
# puts "Requesting ---> #{data.inspect}"
|
85
85
|
http = Net::HTTP.new(@host, @port)
|
86
|
+
http.open_timeout = default_timeout_in_seconds
|
87
|
+
http.read_timeout = default_timeout_in_seconds
|
86
88
|
response = http.post('/selenium-server/driver/', data, HTTP_HEADERS)
|
87
89
|
# puts "RESULT: #{response.inspect}\n"
|
88
90
|
[ response.body[0..1], response.body[3..-1] ]
|
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.13
|
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: 2009-
|
12
|
+
date: 2009-03-07 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -26,8 +26,8 @@ files:
|
|
26
26
|
- lib/selenium/client/base.rb
|
27
27
|
- lib/selenium/client/driver.rb
|
28
28
|
- lib/selenium/client/extensions.rb
|
29
|
-
- lib/selenium/client/generated_driver.rb
|
30
29
|
- lib/selenium/client/idiomatic.rb
|
30
|
+
- lib/selenium/client/javascript_expression_builder.rb
|
31
31
|
- lib/selenium/client/javascript_frameworks/jquery.rb
|
32
32
|
- lib/selenium/client/javascript_frameworks/prototype.rb
|
33
33
|
- lib/selenium/client/protocol.rb
|