webrat 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/Gemfile +0 -6
  2. data/History.txt +17 -0
  3. data/Rakefile +7 -9
  4. data/lib/webrat.rb +1 -1
  5. data/lib/webrat/adapters/mechanize.rb +22 -6
  6. data/lib/webrat/adapters/rack.rb +4 -0
  7. data/lib/webrat/adapters/rails.rb +4 -0
  8. data/lib/webrat/core/configuration.rb +16 -1
  9. data/lib/webrat/core/elements/field.rb +40 -89
  10. data/lib/webrat/core/elements/form.rb +55 -31
  11. data/lib/webrat/core/locators/form_locator.rb +1 -1
  12. data/lib/webrat/core/matchers/have_xpath.rb +4 -2
  13. data/lib/webrat/core/methods.rb +1 -1
  14. data/lib/webrat/core/mime.rb +2 -2
  15. data/lib/webrat/core/scope.rb +1 -0
  16. data/lib/webrat/core/session.rb +4 -3
  17. data/lib/webrat/core_extensions/{nil_to_param.rb → nil_to_query_string.rb} +1 -1
  18. data/lib/webrat/selenium/location_strategy_javascript/label.js +9 -3
  19. data/lib/webrat/selenium/selenium_rc_server.rb +4 -1
  20. data/lib/webrat/selenium/selenium_session.rb +9 -4
  21. data/spec/fakes/test_adapter.rb +1 -1
  22. data/spec/integration/mechanize/sample_app.rb +16 -1
  23. data/spec/integration/mechanize/spec/mechanize_spec.rb +9 -1
  24. data/spec/integration/rack/app.rb +2 -2
  25. data/spec/integration/rack/test/helper.rb +0 -1
  26. data/spec/integration/rack/test/webrat_rack_test.rb +3 -2
  27. data/spec/integration/sinatra/classic_app.rb +0 -1
  28. data/spec/integration/sinatra/modular_app.rb +0 -1
  29. data/spec/integration/sinatra/test/classic_app_test.rb +1 -0
  30. data/spec/integration/sinatra/test/test_helper.rb +0 -1
  31. data/spec/private/core/field_spec.rb +1 -1
  32. data/spec/private/core/form_spec.rb +51 -0
  33. data/spec/private/core/session_spec.rb +5 -18
  34. data/spec/private/mechanize/mechanize_adapter_spec.rb +24 -1
  35. data/spec/private/rails/attaches_file_spec.rb +33 -0
  36. data/spec/public/matchers/have_xpath_spec.rb +6 -0
  37. data/spec/public/submit_form_spec.rb +52 -1
  38. data/spec/spec_helper.rb +0 -1
  39. data/webrat.gemspec +6 -4
  40. 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
- all_params = {}
45
+ query_string = []
46
+ replaces = {}
43
47
 
44
48
  fields.each do |field|
45
- next if field.to_param.nil?
46
- merge(all_params, field.to_param)
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
- all_params
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 merge(all_params, new_param)
61
- new_param.each do |key, value|
62
- case all_params[key]
63
- when *hash_classes
64
- merge_hash_values(all_params[key], value)
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
- all_params[key] += value
67
- else
68
- all_params[key] = value
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 merge_hash_values(a, b) # :nodoc:
74
- a.keys.each do |k|
75
- if b.has_key?(k)
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
- a.merge!(b)
89
+ params
87
90
  end
88
91
 
89
- def hash_classes
90
- klasses = [Hash]
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
- klasses << HashWithIndifferentAccess
107
+ parse_rails_request_params(query_string)
95
108
  when :merb
96
- klasses << Mash
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
@@ -10,7 +10,7 @@ module Webrat
10
10
  end
11
11
 
12
12
  def form_element
13
- @dom.css("#" + @value).first
13
+ @dom.css("#" + @value).first || @dom.css(@value).first
14
14
  end
15
15
 
16
16
  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 && (!@block || @block.call(matched))
20
+ matched.size == @options[:count].to_i
19
21
  else
20
- matched.any? && (!@block || @block.call(matched))
22
+ matched.any?
21
23
  end
22
24
  end
23
25
 
@@ -3,7 +3,7 @@ module Webrat
3
3
 
4
4
  def self.delegate_to_session(*meths)
5
5
  meths.each do |meth|
6
- self.class_eval <<-RUBY
6
+ self.class_eval(<<-RUBY, __FILE__, __LINE__)
7
7
  def #{meth}(*args, &blk)
8
8
  webrat_session.#{meth}(*args, &blk)
9
9
  end
@@ -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) { |type|
12
- raise ArgumentError.new("Invalid Mime type: #{type}")
11
+ MIME_TYPES.fetch(type) { |invalid_type|
12
+ raise ArgumentError.new("Invalid Mime type: #{invalid_type}")
13
13
  }
14
14
  end
15
15
 
@@ -28,6 +28,7 @@ module Webrat
28
28
  attr_reader :session
29
29
 
30
30
  def initialize(session, &block) #:nodoc:
31
+ @selector, @dom = nil
31
32
  @session = session
32
33
  instance_eval(&block) if block_given?
33
34
 
@@ -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 / 100).to_i == 3
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
- response.headers["Location"]
285
+ response_headers['Location']
285
286
  end
286
287
 
287
288
  def current_host
@@ -1,5 +1,5 @@
1
1
  class NilClass #:nodoc:
2
- def to_param
2
+ def to_query_string
3
3
  nil
4
4
  end
5
5
  end
@@ -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 = locatedLabel.getAttribute('for');
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
- :timeout => Webrat.configuration.selenium_browser_startup_timeout)
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
- require "selenium"
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.application_port}")
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
@@ -15,7 +15,7 @@ module Webrat #:nodoc:
15
15
  end
16
16
 
17
17
  def response_code
18
- @response_code || 200
18
+ @response_code ||= 200
19
19
  end
20
20
 
21
21
  def get(url, data, headers = nil)
@@ -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
- it "should submit forms"
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].to_yaml
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,4 +1,3 @@
1
- require "rubygems"
2
1
  require "test/unit"
3
2
  require "rack/test"
4
3
  # require "redgreen"
@@ -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 = YAML.load(response_body)
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
- assert upload[:tempfile].respond_to?(:read)
59
+ assert_equal File.read(__FILE__), upload[:tempfile]
59
60
  end
60
61
  end
61
62
 
@@ -1,4 +1,3 @@
1
- require "rubygems"
2
1
  require "sinatra"
3
2
 
4
3
  use_in_file_templates!
@@ -1,4 +1,3 @@
1
- require "rubygems"
2
1
  require "sinatra/base"
3
2
 
4
3
  class MyModularApp < Sinatra::Default
@@ -1,3 +1,4 @@
1
+ require "rubygems"
1
2
  require File.dirname(__FILE__) + "/test_helper"
2
3
  require File.dirname(__FILE__) + "/../classic_app"
3
4
 
@@ -1,4 +1,3 @@
1
- require "rubygems"
2
1
  require "test/unit"
3
2
  # require "redgreen"
4
3
 
@@ -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.to_param.should == { 'email' => 'user@example.com' }
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