selenium-client 1.2.12 → 1.2.13
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 +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
|