webrat 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +0 -6
- data/History.txt +17 -0
- data/Rakefile +7 -9
- data/lib/webrat.rb +1 -1
- data/lib/webrat/adapters/mechanize.rb +22 -6
- data/lib/webrat/adapters/rack.rb +4 -0
- data/lib/webrat/adapters/rails.rb +4 -0
- data/lib/webrat/core/configuration.rb +16 -1
- data/lib/webrat/core/elements/field.rb +40 -89
- data/lib/webrat/core/elements/form.rb +55 -31
- data/lib/webrat/core/locators/form_locator.rb +1 -1
- data/lib/webrat/core/matchers/have_xpath.rb +4 -2
- data/lib/webrat/core/methods.rb +1 -1
- data/lib/webrat/core/mime.rb +2 -2
- data/lib/webrat/core/scope.rb +1 -0
- data/lib/webrat/core/session.rb +4 -3
- data/lib/webrat/core_extensions/{nil_to_param.rb → nil_to_query_string.rb} +1 -1
- data/lib/webrat/selenium/location_strategy_javascript/label.js +9 -3
- data/lib/webrat/selenium/selenium_rc_server.rb +4 -1
- data/lib/webrat/selenium/selenium_session.rb +9 -4
- data/spec/fakes/test_adapter.rb +1 -1
- data/spec/integration/mechanize/sample_app.rb +16 -1
- data/spec/integration/mechanize/spec/mechanize_spec.rb +9 -1
- data/spec/integration/rack/app.rb +2 -2
- data/spec/integration/rack/test/helper.rb +0 -1
- data/spec/integration/rack/test/webrat_rack_test.rb +3 -2
- data/spec/integration/sinatra/classic_app.rb +0 -1
- data/spec/integration/sinatra/modular_app.rb +0 -1
- data/spec/integration/sinatra/test/classic_app_test.rb +1 -0
- data/spec/integration/sinatra/test/test_helper.rb +0 -1
- data/spec/private/core/field_spec.rb +1 -1
- data/spec/private/core/form_spec.rb +51 -0
- data/spec/private/core/session_spec.rb +5 -18
- data/spec/private/mechanize/mechanize_adapter_spec.rb +24 -1
- data/spec/private/rails/attaches_file_spec.rb +33 -0
- data/spec/public/matchers/have_xpath_spec.rb +6 -0
- data/spec/public/submit_form_spec.rb +52 -1
- data/spec/spec_helper.rb +0 -1
- data/webrat.gemspec +6 -4
- metadata +38 -18
@@ -38,15 +38,24 @@ module Webrat
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
# iterate over all form fields to build a request querystring to get params from it,
|
42
|
+
# for file_field we made a work around to pass a digest as value to later replace it
|
43
|
+
# in params hash with the real file.
|
41
44
|
def params
|
42
|
-
|
45
|
+
query_string = []
|
46
|
+
replaces = {}
|
43
47
|
|
44
48
|
fields.each do |field|
|
45
|
-
next if field.
|
46
|
-
merge(
|
49
|
+
next if field.to_query_string.nil?
|
50
|
+
replaces.merge!({field.digest_value => field.test_uploaded_file}) if field.is_a?(FileField)
|
51
|
+
query_string << field.to_query_string
|
47
52
|
end
|
48
53
|
|
49
|
-
|
54
|
+
query_params = self.class.query_string_to_params(query_string.join('&'))
|
55
|
+
|
56
|
+
query_params = self.class.replace_params_values(query_params, replaces)
|
57
|
+
|
58
|
+
self.class.unescape_params(query_params)
|
50
59
|
end
|
51
60
|
|
52
61
|
def form_method
|
@@ -57,47 +66,62 @@ module Webrat
|
|
57
66
|
@element["action"].blank? ? @session.current_url : @element["action"]
|
58
67
|
end
|
59
68
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
69
|
+
def self.replace_param_value(params, oval, nval)
|
70
|
+
output = Hash.new
|
71
|
+
params.each do |key, value|
|
72
|
+
case value
|
73
|
+
when Hash
|
74
|
+
value = replace_param_value(value, oval, nval)
|
65
75
|
when Array
|
66
|
-
|
67
|
-
|
68
|
-
|
76
|
+
value = value.map { |o| o == oval ? nval : ( o.is_a?(Hash) ? replace_param_value(o, oval, nval) : o) }
|
77
|
+
when oval
|
78
|
+
value = nval
|
69
79
|
end
|
80
|
+
output[key] = value
|
70
81
|
end
|
82
|
+
output
|
71
83
|
end
|
72
84
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
case [a[k], b[k]].map{|value| value.class}
|
77
|
-
when *hash_classes.zip(hash_classes)
|
78
|
-
a[k] = merge_hash_values(a[k], b[k])
|
79
|
-
b.delete(k)
|
80
|
-
when [Array, Array]
|
81
|
-
a[k] += b[k]
|
82
|
-
b.delete(k)
|
83
|
-
end
|
84
|
-
end
|
85
|
+
def self.replace_params_values(params, values)
|
86
|
+
values.each do |key, value|
|
87
|
+
params = replace_param_value(params, key, value)
|
85
88
|
end
|
86
|
-
|
89
|
+
params
|
87
90
|
end
|
88
91
|
|
89
|
-
def
|
90
|
-
|
92
|
+
def self.unescape_params(params)
|
93
|
+
case params.class.name
|
94
|
+
when 'Hash', 'Mash'
|
95
|
+
params.each { |key,value| params[key] = unescape_params(value) }
|
96
|
+
params
|
97
|
+
when 'Array'
|
98
|
+
params.collect { |value| unescape_params(value) }
|
99
|
+
else
|
100
|
+
params.is_a?(String) ? CGI.unescapeHTML(params) : params
|
101
|
+
end
|
102
|
+
end
|
91
103
|
|
104
|
+
def self.query_string_to_params(query_string)
|
92
105
|
case Webrat.configuration.mode
|
93
106
|
when :rails
|
94
|
-
|
107
|
+
parse_rails_request_params(query_string)
|
95
108
|
when :merb
|
96
|
-
|
109
|
+
::Merb::Parse.query(query_string)
|
110
|
+
when :rack, :sinatra
|
111
|
+
Rack::Utils.parse_nested_query(query_string)
|
112
|
+
else
|
113
|
+
query_string.split('&').map {|query| { query.split('=').first => query.split('=').last }}
|
97
114
|
end
|
98
|
-
|
99
|
-
klasses
|
100
115
|
end
|
101
116
|
|
117
|
+
def self.parse_rails_request_params(query_string)
|
118
|
+
if defined?(ActionController::AbstractRequest)
|
119
|
+
ActionController::AbstractRequest.parse_query_parameters(query_string)
|
120
|
+
elsif defined?(ActionController::UrlEncodedPairParser)
|
121
|
+
ActionController::UrlEncodedPairParser.parse_query_parameters(query_string)
|
122
|
+
else
|
123
|
+
Rack::Utils.parse_nested_query(query_string)
|
124
|
+
end
|
125
|
+
end
|
102
126
|
end
|
103
127
|
end
|
@@ -14,10 +14,12 @@ module Webrat
|
|
14
14
|
@block ||= block
|
15
15
|
matched = matches(stringlike)
|
16
16
|
|
17
|
+
@block.call(matched) if @block
|
18
|
+
|
17
19
|
if @options[:count]
|
18
|
-
matched.size == @options[:count].to_i
|
20
|
+
matched.size == @options[:count].to_i
|
19
21
|
else
|
20
|
-
matched.any?
|
22
|
+
matched.any?
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
data/lib/webrat/core/methods.rb
CHANGED
data/lib/webrat/core/mime.rb
CHANGED
@@ -8,8 +8,8 @@ module Webrat #:nodoc:
|
|
8
8
|
def mime_type(type)
|
9
9
|
return type if type.nil? || type.to_s.include?("/")
|
10
10
|
type = ".#{type}" unless type.to_s[0] == ?.
|
11
|
-
MIME_TYPES.fetch(type) { |
|
12
|
-
raise ArgumentError.new("Invalid Mime type: #{
|
11
|
+
MIME_TYPES.fetch(type) { |invalid_type|
|
12
|
+
raise ArgumentError.new("Invalid Mime type: #{invalid_type}")
|
13
13
|
}
|
14
14
|
end
|
15
15
|
|
data/lib/webrat/core/scope.rb
CHANGED
data/lib/webrat/core/session.rb
CHANGED
@@ -65,7 +65,7 @@ For example:
|
|
65
65
|
attr_reader :current_url
|
66
66
|
attr_reader :elements
|
67
67
|
|
68
|
-
def_delegators :@adapter, :response, :response_code, :response_body,
|
68
|
+
def_delegators :@adapter, :response, :response_code, :response_body, :response_headers,
|
69
69
|
:response_body=, :response_code=,
|
70
70
|
:get, :post, :put, :delete
|
71
71
|
|
@@ -75,6 +75,7 @@ For example:
|
|
75
75
|
@data = {}
|
76
76
|
@default_headers = {}
|
77
77
|
@custom_headers = {}
|
78
|
+
@current_url = nil
|
78
79
|
reset
|
79
80
|
end
|
80
81
|
|
@@ -155,7 +156,7 @@ For example:
|
|
155
156
|
end
|
156
157
|
|
157
158
|
def redirect? #:nodoc:
|
158
|
-
(response_code
|
159
|
+
[301, 302, 303, 307].include?(response_code)
|
159
160
|
end
|
160
161
|
|
161
162
|
def internal_redirect?
|
@@ -281,7 +282,7 @@ For example:
|
|
281
282
|
end
|
282
283
|
|
283
284
|
def response_location
|
284
|
-
|
285
|
+
response_headers['Location']
|
285
286
|
end
|
286
287
|
|
287
288
|
def current_host
|
@@ -10,7 +10,7 @@ RegExp.escape = function(text) {
|
|
10
10
|
);
|
11
11
|
}
|
12
12
|
return text.replace(arguments.callee.sRE, '\\$1');
|
13
|
-
}
|
13
|
+
};
|
14
14
|
|
15
15
|
var allLabels = inDocument.getElementsByTagName("label");
|
16
16
|
var regExp = new RegExp('^\\W*' + RegExp.escape(locator) + '(\\b|$)', 'i');
|
@@ -21,7 +21,7 @@ var candidateLabels = $A(allLabels).select(function(candidateLabel){
|
|
21
21
|
});
|
22
22
|
|
23
23
|
if (candidateLabels.length == 0) {
|
24
|
-
return null;
|
24
|
+
return null;
|
25
25
|
}
|
26
26
|
|
27
27
|
//reverse length sort
|
@@ -30,7 +30,13 @@ candidateLabels = candidateLabels.sortBy(function(s) {
|
|
30
30
|
});
|
31
31
|
|
32
32
|
var locatedLabel = candidateLabels.first();
|
33
|
-
var labelFor =
|
33
|
+
var labelFor = null;
|
34
|
+
|
35
|
+
if (locatedLabel.getAttribute('for')) {
|
36
|
+
labelFor = locatedLabel.getAttribute('for');
|
37
|
+
} else if (locatedLabel.attributes['for']) { // IE
|
38
|
+
labelFor = locatedLabel.attributes['for'].nodeValue;
|
39
|
+
}
|
34
40
|
|
35
41
|
if ((labelFor == null) && (locatedLabel.hasChildNodes())) {
|
36
42
|
return locatedLabel.getElementsByTagName('button')[0]
|
@@ -31,10 +31,13 @@ module Webrat
|
|
31
31
|
|
32
32
|
def remote_control
|
33
33
|
return @remote_control if @remote_control
|
34
|
+
server_options = { :timeout => Webrat.configuration.selenium_browser_startup_timeout }
|
35
|
+
server_options[:firefox_profile] = Webrat.configuration.selenium_firefox_profile if Webrat.configuration.selenium_firefox_profile
|
34
36
|
|
35
37
|
@remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0",
|
36
38
|
Webrat.configuration.selenium_server_port,
|
37
|
-
|
39
|
+
server_options)
|
40
|
+
|
38
41
|
@remote_control.jar_file = jar_path
|
39
42
|
|
40
43
|
return @remote_control
|
@@ -3,7 +3,12 @@ require "webrat/selenium/selenium_rc_server"
|
|
3
3
|
require "webrat/selenium/application_server_factory"
|
4
4
|
require "webrat/selenium/application_servers/base"
|
5
5
|
|
6
|
-
|
6
|
+
begin
|
7
|
+
require "selenium"
|
8
|
+
rescue LoadError => e
|
9
|
+
e.message << " (You may need to install the selenium-rc gem)"
|
10
|
+
raise e
|
11
|
+
end
|
7
12
|
|
8
13
|
module Webrat
|
9
14
|
class TimeoutError < WebratError
|
@@ -170,8 +175,8 @@ module Webrat
|
|
170
175
|
end
|
171
176
|
|
172
177
|
error_message = "#{message} (after #{timeout} sec)"
|
173
|
-
|
174
|
-
if $browser
|
178
|
+
|
179
|
+
if $browser && Webrat.configuration.selenium_verbose_output
|
175
180
|
error_message += <<-EOS
|
176
181
|
|
177
182
|
|
@@ -232,7 +237,7 @@ EOS
|
|
232
237
|
|
233
238
|
def create_browser
|
234
239
|
$browser = ::Selenium::Client::Driver.new(Webrat.configuration.selenium_server_address || "localhost",
|
235
|
-
Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_browser_key, "http://#{Webrat.configuration.application_address}:#{Webrat.configuration.
|
240
|
+
Webrat.configuration.selenium_server_port, Webrat.configuration.selenium_browser_key, "http://#{Webrat.configuration.application_address}:#{Webrat.configuration.application_port_for_selenium}")
|
236
241
|
$browser.set_speed(0) unless Webrat.configuration.selenium_server_address
|
237
242
|
|
238
243
|
at_exit do
|
data/spec/fakes/test_adapter.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require "rubygems"
|
2
1
|
require "sinatra/base"
|
3
2
|
|
4
3
|
class SampleApp < Sinatra::Default
|
@@ -17,4 +16,20 @@ class SampleApp < Sinatra::Default
|
|
17
16
|
get "/redirected" do
|
18
17
|
"Redirected"
|
19
18
|
end
|
19
|
+
|
20
|
+
get "/form" do
|
21
|
+
<<-EOS
|
22
|
+
<html>
|
23
|
+
<form action="/form" method="post">
|
24
|
+
<input type="hidden" name="_method" value="put" />
|
25
|
+
<label for="email">Email:</label> <input type="text" id="email" name="email" /></label>
|
26
|
+
<input type="submit" value="Add" />
|
27
|
+
</form>
|
28
|
+
</html>
|
29
|
+
EOS
|
30
|
+
end
|
31
|
+
|
32
|
+
put "/form" do
|
33
|
+
"Welcome #{params[:email]}"
|
34
|
+
end
|
20
35
|
end
|
@@ -12,7 +12,15 @@ describe "Webrat's Mechanize mode" do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should follow links"
|
15
|
-
|
15
|
+
|
16
|
+
it "should submit forms" do
|
17
|
+
visit "http://localhost:9292/form"
|
18
|
+
fill_in "Email", :with => "albert@example.com"
|
19
|
+
response = click_button "Add"
|
20
|
+
|
21
|
+
response.should contain("Welcome albert@example.com")
|
22
|
+
end
|
23
|
+
|
16
24
|
it "should not follow external redirects" do
|
17
25
|
pending do
|
18
26
|
response = visit("http://localhost:9292/external_redirect")
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "rubygems"
|
2
1
|
require "sinatra/base"
|
3
2
|
|
4
3
|
class RackApp < Sinatra::Base
|
@@ -39,7 +38,8 @@ class RackApp < Sinatra::Base
|
|
39
38
|
end
|
40
39
|
|
41
40
|
post "/upload" do
|
42
|
-
params[:uploaded_file]
|
41
|
+
uploaded_file = params[:uploaded_file]
|
42
|
+
Marshal.dump(:tempfile => uploaded_file[:tempfile].read, :type => uploaded_file[:type], :filename => uploaded_file[:filename])
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require "rubygems"
|
1
2
|
require File.dirname(__FILE__) + "/helper"
|
2
3
|
|
3
4
|
class WebratRackTest < Test::Unit::TestCase
|
@@ -52,10 +53,10 @@ class WebratRackTest < Test::Unit::TestCase
|
|
52
53
|
attach_file "File", __FILE__, "text/ruby"
|
53
54
|
click_button "Upload"
|
54
55
|
|
55
|
-
upload =
|
56
|
+
upload = Marshal.load(response_body)
|
56
57
|
assert_equal "text/ruby", upload[:type]
|
57
58
|
assert_equal "webrat_rack_test.rb", upload[:filename]
|
58
|
-
|
59
|
+
assert_equal File.read(__FILE__), upload[:tempfile]
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
@@ -77,7 +77,7 @@ module Webrat
|
|
77
77
|
|
78
78
|
element = Webrat::XML.document(html).css('input').first
|
79
79
|
text_field = TextField.new(nil, element)
|
80
|
-
text_field.
|
80
|
+
text_field.to_query_string.should == 'email=user@example.com'
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe "Multiple nested params" do
|
4
|
+
it "should be corretly posted" do
|
5
|
+
Webrat.configuration.mode = :rails
|
6
|
+
|
7
|
+
with_html <<-HTML
|
8
|
+
<html>
|
9
|
+
<form method="post" action="/family">
|
10
|
+
<div class="couple">
|
11
|
+
<div class="parent">
|
12
|
+
<select name="user[family][parents][0][][gender]">
|
13
|
+
<option selected="selected" value="Mother">Mother</option>
|
14
|
+
<option value="Father">Father</option>
|
15
|
+
</select>
|
16
|
+
<input type="text" value="Alice" name="user[family][parents][0][][name]" />
|
17
|
+
</div>
|
18
|
+
<div class="parent">
|
19
|
+
<select name="user[family][parents][0][][gender]">
|
20
|
+
<option value="Mother">Mother</option>
|
21
|
+
<option selected="selected" value="Father">Father</option>
|
22
|
+
</select>
|
23
|
+
<input type="text" value="Michael" name="user[family][parents][0][][name]" />
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
<div class="couple">
|
27
|
+
<div class="parent">
|
28
|
+
<select name="user[family][parents][1][][gender]">
|
29
|
+
<option selected="selected" value="Mother">Mother</option>
|
30
|
+
<option value="Father">Father</option>
|
31
|
+
</select>
|
32
|
+
<input type="text" value="Jenny" name="user[family][parents][1][][name]" />
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
<input type="submit" />
|
36
|
+
</form>
|
37
|
+
</html>
|
38
|
+
HTML
|
39
|
+
|
40
|
+
params = { "user" => { "family" => { "parents" => {
|
41
|
+
"0" => [ {"name" => "Alice", "gender"=>"Mother"}, {"name" => "Michael", "gender"=>"Father"} ],
|
42
|
+
"1" => [ {"name" => "Jenny", "gender"=>"Mother"} ]
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
webrat_session.should_receive(:post).with("/family", params)
|
49
|
+
click_button
|
50
|
+
end
|
51
|
+
end
|