capybara 0.4.0 → 0.4.1.rc
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +35 -0
- data/README.rdoc +60 -19
- data/lib/capybara.rb +81 -5
- data/lib/capybara/driver/base.rb +1 -6
- data/lib/capybara/driver/celerity_driver.rb +19 -9
- data/lib/capybara/driver/node.rb +8 -0
- data/lib/capybara/driver/rack_test_driver.rb +42 -29
- data/lib/capybara/driver/selenium_driver.rb +11 -3
- data/lib/capybara/dsl.rb +11 -0
- data/lib/capybara/node/actions.rb +4 -14
- data/lib/capybara/node/base.rb +47 -0
- data/lib/capybara/node/document.rb +17 -0
- data/lib/capybara/node/element.rb +178 -0
- data/lib/capybara/node/finders.rb +78 -27
- data/lib/capybara/node/matchers.rb +40 -11
- data/lib/capybara/node/simple.rb +116 -0
- data/lib/capybara/rspec.rb +18 -0
- data/lib/capybara/server.rb +5 -10
- data/lib/capybara/session.rb +7 -16
- data/lib/capybara/spec/driver.rb +16 -1
- data/lib/capybara/spec/session.rb +1 -0
- data/lib/capybara/spec/session/all_spec.rb +5 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +2 -3
- data/lib/capybara/spec/session/find_spec.rb +0 -6
- data/lib/capybara/spec/session/first_spec.rb +72 -0
- data/lib/capybara/spec/session/has_css_spec.rb +107 -1
- data/lib/capybara/spec/session/has_field_spec.rb +60 -0
- data/lib/capybara/spec/session/has_select_spec.rb +40 -0
- data/lib/capybara/spec/session/javascript.rb +4 -13
- data/lib/capybara/spec/session/within_spec.rb +10 -3
- data/lib/capybara/spec/test_app.rb +20 -1
- data/lib/capybara/spec/views/form.erb +27 -0
- data/lib/capybara/spec/views/with_html.erb +21 -5
- data/lib/capybara/util/save_and_open_page.rb +8 -5
- data/lib/capybara/version.rb +1 -1
- data/spec/basic_node_spec.rb +77 -0
- data/spec/capybara_spec.rb +18 -0
- data/spec/dsl_spec.rb +26 -0
- data/spec/rspec_spec.rb +47 -0
- data/spec/save_and_open_page_spec.rb +83 -7
- data/spec/server_spec.rb +20 -0
- data/spec/session/rack_test_session_spec.rb +10 -0
- data/spec/string_spec.rb +77 -0
- metadata +306 -295
- data/lib/capybara/node.rb +0 -221
data/History.txt
CHANGED
@@ -1,3 +1,38 @@
|
|
1
|
+
# Version 0.4.1
|
2
|
+
|
3
|
+
Release date:
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
* New click_on alias for click_link_or_button, shorter yet unambiguous. [Jonas Nicklas]
|
8
|
+
* Finders now accept :visible => false which will find all elements regardless of Capybara.ignore_hidden_elements [Jonas Nicklas]
|
9
|
+
* Configure how the server is started via Capybara.server { |app, port| ... }. [John Firebough]
|
10
|
+
* Added :between, :maximum and :minimum options to has_selector and friends [James B. Byrne]
|
11
|
+
* New Capybara.string util function which allows matchers on arbitrary strings, mostly for helper and view specs [David Chelimsky and Jonas Nicklas]
|
12
|
+
* Server boot timeout is now configurable, via Capybara.server_boot_timeout [Adam Cigánek]
|
13
|
+
* Built in support for RSpec [Jonas Nicklas]
|
14
|
+
* Capybara.using_driver to switch to a different driver temporarily [Jeff Kreeftmeijer]
|
15
|
+
* Added Session#first which is somewhat speedier than Session#all, use it internally for speed boost [John Firebaugh]
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
* Session#within now accepts the same arguments as other finders, like Session#all and Session#find [Jonas Nicklas]
|
20
|
+
|
21
|
+
### Removed
|
22
|
+
|
23
|
+
* All deprecations from 0.4.0 have been removed. [Jonas Nicklas]
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
|
27
|
+
* Don't mangle URLs in save_and_open_page when using self-closing tags [Adam Spiers]
|
28
|
+
* Catch correct error when server boot times out [Jonas Nicklas]
|
29
|
+
* Celerity driver now properly passes through options, making it configurable [Jonas Nicklas]
|
30
|
+
* Better implementation of attributes in C[ue]lerity, should fix issues with attributes with strange names [Jonas Nicklas]
|
31
|
+
* Session#find no longer swallows errors [Jonas Nicklas]
|
32
|
+
* Fix problems with multiple file inputs [Philip Arndt]
|
33
|
+
* Submit multipart forms as multipart under rack-test even if they contain no files [Ryan Kinderman]
|
34
|
+
* Matchers like has_select? and has_checked_field? now work with dynamically changed values [John Firebaugh]
|
35
|
+
|
1
36
|
# Version 0.4.0
|
2
37
|
|
3
38
|
Release date: 2010-10-22
|
data/README.rdoc
CHANGED
@@ -64,6 +64,57 @@ Now you can use it in your steps:
|
|
64
64
|
click_link 'Sign in'
|
65
65
|
end
|
66
66
|
|
67
|
+
Capybara sets up some {tags}[http://wiki.github.com/aslakhellesoy/cucumber/tags]
|
68
|
+
for you to use in Cucumber. Often you'll want to run only some scenarios with a
|
69
|
+
driver that supports JavaScript, Capybara makes this easy: simply tag the
|
70
|
+
scenario (or feature) with <tt>@javascript</tt>:
|
71
|
+
|
72
|
+
@javascript
|
73
|
+
Scenario: do something AJAXy
|
74
|
+
When I click the AJAX link
|
75
|
+
...
|
76
|
+
|
77
|
+
You can change which driver Capybara uses for JavaScript:
|
78
|
+
|
79
|
+
Capybara.javascript_driver = :culerity
|
80
|
+
|
81
|
+
There are also explicit <tt>@selenium</tt>, <tt>@culerity</tt> and
|
82
|
+
<tt>@rack_test</tt> tags set up for you.
|
83
|
+
|
84
|
+
== Using Capybara with RSpec
|
85
|
+
|
86
|
+
If you prefer RSpec to using Cucumber, you can use the built in RSpec support:
|
87
|
+
|
88
|
+
require 'capybara/rspec'
|
89
|
+
Capybara.app = MyRackApp
|
90
|
+
|
91
|
+
You can now use it in your examples:
|
92
|
+
|
93
|
+
describe "the signup process", :type => :acceptance do
|
94
|
+
it "signs me in" do
|
95
|
+
within("#session") do
|
96
|
+
fill_in 'Login', :with => 'user@example.com'
|
97
|
+
fill_in 'Password', :with => 'password'
|
98
|
+
end
|
99
|
+
click_link 'Sign in'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
Capybara is only included for examples which have the type
|
104
|
+
<tt>:acceptance</tt>.
|
105
|
+
|
106
|
+
RSpec's metadata feature can be used to switch to a different driver. Use
|
107
|
+
<tt>:js => true</tt> to switch to the javascript driver, or provide a
|
108
|
+
<tt>:driver</tt> option to switch to one specific driver. For example:
|
109
|
+
|
110
|
+
describe 'some stuff which requires js', :js => true do
|
111
|
+
it 'will use the default js driver'
|
112
|
+
it 'will switch to one specific driver', :driver => :celerity
|
113
|
+
end
|
114
|
+
|
115
|
+
Note that Capybara's built in RSpec support only works with RSpec 2.0 or later.
|
116
|
+
You'll need to roll your own for earlier versions of RSpec.
|
117
|
+
|
67
118
|
== Default and current driver
|
68
119
|
|
69
120
|
You can set up a default driver for your features. For example if you'd prefer
|
@@ -82,25 +133,6 @@ You can do this in Before and After blocks to temporarily switch to a different
|
|
82
133
|
driver. Note that switching driver creates a new session, so you may not be able
|
83
134
|
to switch in the middle of a Scenario.
|
84
135
|
|
85
|
-
== Cucumber and Tags
|
86
|
-
|
87
|
-
Capybara sets up some {tags}[http://wiki.github.com/aslakhellesoy/cucumber/tags]
|
88
|
-
for you to use in Cucumber. Often you'll want to run only some scenarios with a
|
89
|
-
driver that supports JavaScript, Capybara makes this easy: simply tag the
|
90
|
-
scenario (or feature) with <tt>@javascript</tt>:
|
91
|
-
|
92
|
-
@javascript
|
93
|
-
Scenario: do something AJAXy
|
94
|
-
When I click the AJAX link
|
95
|
-
...
|
96
|
-
|
97
|
-
You can change which driver Capybara uses for JavaScript:
|
98
|
-
|
99
|
-
Capybara.javascript_driver = :culerity
|
100
|
-
|
101
|
-
There are also explicit <tt>@selenium</tt>, <tt>@culerity</tt> and
|
102
|
-
<tt>@rack_test</tt> tags set up for you.
|
103
|
-
|
104
136
|
== Selenium
|
105
137
|
|
106
138
|
At the moment, Capybara supports Webdriver, also called Selenium 2.0, *not*
|
@@ -456,6 +488,9 @@ Whatever is returned from the block should conform to the API described by
|
|
456
488
|
Capybara::Driver::Base, it does not however have to inherit from this class.
|
457
489
|
Gems can use this API to add their own drivers to Capybara.
|
458
490
|
|
491
|
+
The {Selenium wiki}[http://code.google.com/p/selenium/wiki/RubyBindings] has
|
492
|
+
additional info about how the underlying driver can be configured.
|
493
|
+
|
459
494
|
== Gotchas:
|
460
495
|
|
461
496
|
* Access to session and request is not possible from the test, Access to
|
@@ -473,6 +508,12 @@ Gems can use this API to add their own drivers to Capybara.
|
|
473
508
|
use plugins which allow you to travel in time, rather than freeze time.
|
474
509
|
One such plugin is {Timecop}[http://github.com/jtrupiano/timecop].
|
475
510
|
|
511
|
+
* When using Rack::Test, beware if attempting to visit absolute URLs. For
|
512
|
+
example, a session might not be shared between visits to <tt>posts_path</tt>
|
513
|
+
and <tt>posts_url</tt>. If testing an absolute URL in an Action Mailer email,
|
514
|
+
set <tt>default_url_options</tt> to match the Rails default of
|
515
|
+
<tt>www.example.com</tt>.
|
516
|
+
|
476
517
|
== License:
|
477
518
|
|
478
519
|
(The MIT License)
|
data/lib/capybara.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'timeout'
|
2
2
|
require 'nokogiri'
|
3
3
|
require 'xpath'
|
4
|
-
|
5
4
|
module Capybara
|
6
5
|
class CapybaraError < StandardError; end
|
7
6
|
class DriverNotFoundError < CapybaraError; end
|
@@ -14,7 +13,7 @@ module Capybara
|
|
14
13
|
|
15
14
|
class << self
|
16
15
|
attr_accessor :asset_root, :app_host, :run_server, :default_host
|
17
|
-
attr_accessor :server_port
|
16
|
+
attr_accessor :server_port, :server_boot_timeout
|
18
17
|
attr_accessor :default_selector, :default_wait_time, :ignore_hidden_elements
|
19
18
|
attr_accessor :save_and_open_page_path
|
20
19
|
|
@@ -108,6 +107,74 @@ module Capybara
|
|
108
107
|
@drivers ||= {}
|
109
108
|
end
|
110
109
|
|
110
|
+
##
|
111
|
+
#
|
112
|
+
# Register a proc that Capybara will call to run the Rack application.
|
113
|
+
#
|
114
|
+
# Capybara.server do |app, port|
|
115
|
+
# require 'rack/handler/mongrel'
|
116
|
+
# Rack::Handler::Mongrel.run(app, :Port => port)
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# By default, Capybara will try to run thin, falling back to webrick.
|
120
|
+
#
|
121
|
+
# @yield [app, port] This block recieves a rack app and port and should run a Rack handler
|
122
|
+
#
|
123
|
+
def server(&block)
|
124
|
+
if block_given?
|
125
|
+
@server = block
|
126
|
+
else
|
127
|
+
@server
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
#
|
133
|
+
# Wraps the given string, which should contain an HTML document or fragment
|
134
|
+
# in a {Capybara::Node::Simple} which exposes all {Capybara::Node::Matchers} and
|
135
|
+
# {Capybara::Node::Finders}. This allows you to query any string containing
|
136
|
+
# HTML in the exact same way you would query the current document in a Capybara
|
137
|
+
# session. For example:
|
138
|
+
#
|
139
|
+
# node = Capybara.string <<-HTML
|
140
|
+
# <ul>
|
141
|
+
# <li id="home">Home</li>
|
142
|
+
# <li id="projects">Projects</li>
|
143
|
+
# </ul>
|
144
|
+
# HTML
|
145
|
+
#
|
146
|
+
# node.find('#projects').text # => 'Projects'
|
147
|
+
# node.has_selector?('li#home', :text => 'Home')
|
148
|
+
# node.has_selector?(:projects)
|
149
|
+
# node.find('ul').find('li').text # => 'Home'
|
150
|
+
#
|
151
|
+
# @param [String] html An html fragment or document
|
152
|
+
# @return [Capybara::Node::Simple] A node which has Capybara's finders and matchers
|
153
|
+
#
|
154
|
+
def string(html)
|
155
|
+
Capybara::Node::Simple.new(html)
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
#
|
160
|
+
# Runs Capybara's default server for the given application and port
|
161
|
+
# under most circumstances you should not have to call this method
|
162
|
+
# manually.
|
163
|
+
#
|
164
|
+
# @param [Rack Application] app The rack application to run
|
165
|
+
# @param [Fixnum] port The port to run the application on
|
166
|
+
#
|
167
|
+
def run_default_server(app, port)
|
168
|
+
begin
|
169
|
+
require 'rack/handler/thin'
|
170
|
+
Thin::Logging.silent = true
|
171
|
+
Rack::Handler::Thin.run(app, :Port => port)
|
172
|
+
rescue LoadError
|
173
|
+
require 'rack/handler/webrick'
|
174
|
+
Rack::Handler::WEBrick.run(app, :Port => port, :AccessLog => [], :Logger => WEBrick::Log::new(nil, 0))
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
111
178
|
def deprecate(method, alternate_method)
|
112
179
|
warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead"
|
113
180
|
end
|
@@ -115,12 +182,19 @@ module Capybara
|
|
115
182
|
|
116
183
|
autoload :Server, 'capybara/server'
|
117
184
|
autoload :Session, 'capybara/session'
|
118
|
-
autoload :Node, 'capybara/node'
|
119
|
-
autoload :Document, 'capybara/node'
|
120
|
-
autoload :Element, 'capybara/node'
|
121
185
|
autoload :Selector, 'capybara/selector'
|
122
186
|
autoload :VERSION, 'capybara/version'
|
123
187
|
|
188
|
+
module Node
|
189
|
+
autoload :Base, 'capybara/node/base'
|
190
|
+
autoload :Simple, 'capybara/node/simple'
|
191
|
+
autoload :Element, 'capybara/node/element'
|
192
|
+
autoload :Document, 'capybara/node/document'
|
193
|
+
autoload :Finders, 'capybara/node/finders'
|
194
|
+
autoload :Matchers, 'capybara/node/matchers'
|
195
|
+
autoload :Actions, 'capybara/node/actions'
|
196
|
+
end
|
197
|
+
|
124
198
|
module Driver
|
125
199
|
autoload :Base, 'capybara/driver/base'
|
126
200
|
autoload :Node, 'capybara/driver/node'
|
@@ -133,6 +207,8 @@ end
|
|
133
207
|
|
134
208
|
Capybara.configure do |config|
|
135
209
|
config.run_server = true
|
210
|
+
config.server {|app, port| Capybara.run_default_server(app, port)}
|
211
|
+
config.server_boot_timeout = 10
|
136
212
|
config.default_selector = :css
|
137
213
|
config.default_wait_time = 2
|
138
214
|
config.ignore_hidden_elements = false
|
data/lib/capybara/driver/base.rb
CHANGED
@@ -30,7 +30,7 @@ class Capybara::Driver::Base
|
|
30
30
|
def response_headers
|
31
31
|
raise Capybara::NotSupportedByDriverError
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def status_code
|
35
35
|
raise Capybara::NotSupportedByDriverError
|
36
36
|
end
|
@@ -53,11 +53,6 @@ class Capybara::Driver::Base
|
|
53
53
|
def reset!
|
54
54
|
end
|
55
55
|
|
56
|
-
def cleanup!
|
57
|
-
Capybara.deprecate("cleanup!", "reset!")
|
58
|
-
reset!
|
59
|
-
end
|
60
|
-
|
61
56
|
def has_shortcircuit_timeout?
|
62
57
|
false
|
63
58
|
end
|
@@ -5,19 +5,15 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def [](name)
|
8
|
-
value =
|
9
|
-
native.class_name
|
10
|
-
else
|
11
|
-
native.send(name.to_sym)
|
12
|
-
end
|
8
|
+
value = native.attribute_value(name.to_sym)
|
13
9
|
return value if value and not value.to_s.empty?
|
14
10
|
end
|
15
11
|
|
16
12
|
def value
|
17
13
|
if tag_name == "select" and native.multiple?
|
18
|
-
find(".//option[@selected]").map { |n| n.value
|
14
|
+
find(".//option[@selected]").map { |n| if n.has_value? then n.value else n.text end }
|
19
15
|
else
|
20
|
-
|
16
|
+
native.value
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
@@ -60,6 +56,18 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
|
|
60
56
|
native.visible?
|
61
57
|
end
|
62
58
|
|
59
|
+
def checked?
|
60
|
+
native.checked?
|
61
|
+
rescue # https://github.com/langalex/culerity/issues/issue/33
|
62
|
+
false
|
63
|
+
end
|
64
|
+
|
65
|
+
def selected?
|
66
|
+
native.selected?
|
67
|
+
rescue # https://github.com/langalex/culerity/issues/issue/33
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
63
71
|
def path
|
64
72
|
native.xpath
|
65
73
|
end
|
@@ -81,7 +89,9 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
|
|
81
89
|
find('./ancestor::select').first
|
82
90
|
end
|
83
91
|
|
84
|
-
|
92
|
+
def has_value?
|
93
|
+
native.object.hasAttribute('value')
|
94
|
+
end
|
85
95
|
end
|
86
96
|
|
87
97
|
attr_reader :app, :rack_server, :options
|
@@ -135,7 +145,7 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
|
|
135
145
|
def browser
|
136
146
|
unless @_browser
|
137
147
|
require 'celerity'
|
138
|
-
@_browser = ::Celerity::Browser.new(
|
148
|
+
@_browser = ::Celerity::Browser.new(options)
|
139
149
|
end
|
140
150
|
|
141
151
|
@_browser
|
data/lib/capybara/driver/node.rb
CHANGED
@@ -11,28 +11,11 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def [](name)
|
14
|
-
|
15
|
-
case
|
16
|
-
when 'select' == tag_name && 'value' == attr_name
|
17
|
-
if native['multiple'] == 'multiple'
|
18
|
-
native.xpath(".//option[@selected='selected']").map { |option| option[:value] || option.content }
|
19
|
-
else
|
20
|
-
option = native.xpath(".//option[@selected='selected']").first || native.xpath(".//option").first
|
21
|
-
option[:value] || option.content if option
|
22
|
-
end
|
23
|
-
when 'input' == tag_name && 'checkbox' == type && 'checked' == attr_name
|
24
|
-
native[attr_name] == 'checked' ? true : false
|
25
|
-
else
|
26
|
-
native[attr_name]
|
27
|
-
end
|
14
|
+
string_node[name]
|
28
15
|
end
|
29
16
|
|
30
17
|
def value
|
31
|
-
|
32
|
-
native.content
|
33
|
-
else
|
34
|
-
self[:value]
|
35
|
-
end
|
18
|
+
string_node.value
|
36
19
|
end
|
37
20
|
|
38
21
|
def set(value)
|
@@ -82,7 +65,15 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
82
65
|
end
|
83
66
|
|
84
67
|
def visible?
|
85
|
-
|
68
|
+
string_node.visible?
|
69
|
+
end
|
70
|
+
|
71
|
+
def checked?
|
72
|
+
self[:checked]
|
73
|
+
end
|
74
|
+
|
75
|
+
def selected?
|
76
|
+
self[:selected]
|
86
77
|
end
|
87
78
|
|
88
79
|
def path
|
@@ -95,6 +86,10 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
95
86
|
|
96
87
|
private
|
97
88
|
|
89
|
+
def string_node
|
90
|
+
@string_node ||= Capybara::Node::Simple.new(native)
|
91
|
+
end
|
92
|
+
|
98
93
|
# a reference to the select node if this is an option node
|
99
94
|
def select_node
|
100
95
|
find('./ancestor::select').first
|
@@ -110,10 +105,25 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
110
105
|
end
|
111
106
|
|
112
107
|
class Form < Node
|
108
|
+
# This only needs to inherit from Rack::Test::UploadedFile because Rack::Test checks for
|
109
|
+
# the class specifically when determing whether to consturct the request as multipart.
|
110
|
+
# That check should be based solely on the form element's 'enctype' attribute value,
|
111
|
+
# which should probably be provided to Rack::Test in its non-GET request methods.
|
112
|
+
class NilUploadedFile < Rack::Test::UploadedFile
|
113
|
+
def initialize
|
114
|
+
@empty_file = Tempfile.new("nil_uploaded_file")
|
115
|
+
@empty_file.close
|
116
|
+
end
|
117
|
+
|
118
|
+
def original_filename; ""; end
|
119
|
+
def content_type; "application/octet-stream"; end
|
120
|
+
def path; @empty_file.path; end
|
121
|
+
end
|
122
|
+
|
113
123
|
def params(button)
|
114
124
|
params = {}
|
115
125
|
|
116
|
-
native.xpath(".//input[not(@disabled) and (not(@type) or (@type!='radio' and @type!='checkbox' and @type!='submit' and @type!='image'))]").map do |input|
|
126
|
+
native.xpath(".//input[not(@disabled) and (not(@type) or (@type!='radio' and @type!='file' and @type!='checkbox' and @type!='submit' and @type!='image'))]").map do |input|
|
117
127
|
merge_param!(params, input['name'].to_s, input['value'].to_s)
|
118
128
|
end
|
119
129
|
native.xpath(".//textarea[not(@disabled)]").map do |textarea|
|
@@ -135,14 +145,17 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
135
145
|
end
|
136
146
|
end
|
137
147
|
native.xpath(".//input[not(@disabled) and @type='file']").map do |input|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
148
|
+
if multipart?
|
149
|
+
file = \
|
150
|
+
if (value = input['value']).to_s.empty?
|
151
|
+
NilUploadedFile.new
|
152
|
+
else
|
153
|
+
content_type = MIME::Types.type_for(value).first.to_s
|
154
|
+
Rack::Test::UploadedFile.new(value, content_type)
|
155
|
+
end
|
156
|
+
merge_param!(params, input['name'].to_s, file)
|
157
|
+
else
|
158
|
+
merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s))
|
146
159
|
end
|
147
160
|
end
|
148
161
|
merge_param!(params, button[:name], button[:value] || "") if button[:name]
|