forme 1.11.0 → 2.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG +54 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +235 -209
- data/Rakefile +1 -7
- data/lib/forme/bs3.rb +18 -4
- data/lib/forme/erb.rb +13 -25
- data/lib/forme/form.rb +144 -149
- data/lib/forme/input.rb +1 -1
- data/lib/forme/rails.rb +39 -83
- data/lib/forme/raw.rb +2 -2
- data/lib/forme/tag.rb +3 -12
- data/lib/forme/template.rb +110 -0
- data/lib/forme/transformers/formatter.rb +4 -1
- data/lib/forme/transformers/helper.rb +0 -1
- data/lib/forme/transformers/inputs_wrapper.rb +4 -4
- data/lib/forme/version.rb +2 -2
- data/lib/forme.rb +15 -2
- data/lib/roda/plugins/forme.rb +1 -1
- data/lib/roda/plugins/forme_erubi_capture.rb +57 -0
- data/lib/roda/plugins/forme_route_csrf.rb +16 -34
- data/lib/roda/plugins/forme_set.rb +39 -76
- data/lib/sequel/plugins/forme.rb +40 -50
- data/lib/sequel/plugins/forme_i18n.rb +3 -1
- data/lib/sequel/plugins/forme_set.rb +3 -1
- data/spec/all.rb +1 -1
- data/spec/bs3_reference_spec.rb +18 -18
- data/spec/bs3_sequel_plugin_spec.rb +17 -17
- data/spec/bs3_spec.rb +23 -11
- data/spec/erb_helper.rb +69 -58
- data/spec/erubi_capture_helper.rb +198 -0
- data/spec/forme_spec.rb +21 -32
- data/spec/rails_integration_spec.rb +39 -25
- data/spec/roda_integration_spec.rb +118 -70
- data/spec/sequel_helper.rb +0 -1
- data/spec/sequel_i18n_helper.rb +1 -1
- data/spec/sequel_i18n_plugin_spec.rb +3 -2
- data/spec/sequel_plugin_spec.rb +29 -12
- data/spec/sequel_set_plugin_spec.rb +9 -2
- data/spec/shared_erb_specs.rb +71 -0
- data/spec/sinatra_integration_spec.rb +5 -6
- data/spec/spec_helper.rb +21 -8
- metadata +9 -7
- data/lib/forme/erb_form.rb +0 -74
- data/lib/forme/sinatra.rb +0 -17
@@ -1,8 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require_relative 'sequel_helper'
|
3
|
+
require_relative 'erb_helper'
|
4
4
|
|
5
|
-
require 'rubygems'
|
6
5
|
begin
|
7
6
|
require 'roda'
|
8
7
|
require 'tilt'
|
@@ -17,34 +16,39 @@ rescue LoadError
|
|
17
16
|
rescue LoadError
|
18
17
|
require 'tilt/erb'
|
19
18
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
if defined?(Roda::RodaVersionNumber) && Roda::RodaVersionNumber >= 30100
|
26
|
-
require 'roda/session_middleware'
|
27
|
-
opts[:sessions_convert_symbols] = true
|
28
|
-
use RodaSessionMiddleware, :secret=>SecureRandom.random_bytes(64), :key=>'rack.session'
|
29
|
-
else
|
30
|
-
use Rack::Session::Cookie, :secret => "__a_very_long_string__"
|
31
|
-
end
|
32
|
-
|
33
|
-
def erb(s, opts={})
|
34
|
-
render(opts.merge(:inline=>s))
|
19
|
+
else
|
20
|
+
begin
|
21
|
+
require 'erubi/capture_end'
|
22
|
+
require_relative 'erubi_capture_helper'
|
23
|
+
rescue LoadError
|
35
24
|
end
|
25
|
+
end
|
36
26
|
|
37
|
-
|
38
|
-
|
39
|
-
|
27
|
+
def FormeRodaTest(block=ERB_BLOCK)
|
28
|
+
Class.new(Roda) do
|
29
|
+
opts[:check_dynamic_arity] = opts[:check_arity] = :warn
|
30
|
+
|
31
|
+
if defined?(Roda::RodaVersionNumber) && Roda::RodaVersionNumber >= 30100
|
32
|
+
require 'roda/session_middleware'
|
33
|
+
opts[:sessions_convert_symbols] = true
|
34
|
+
use RodaSessionMiddleware, :secret=>SecureRandom.random_bytes(64), :key=>'rack.session'
|
35
|
+
else
|
36
|
+
use Rack::Session::Cookie, :secret => "__a_very_long_string__"
|
40
37
|
end
|
41
|
-
|
42
|
-
|
38
|
+
|
39
|
+
def erb(s, opts={})
|
40
|
+
render(opts.merge(:inline=>s))
|
43
41
|
end
|
44
|
-
|
45
|
-
|
42
|
+
|
43
|
+
route do |r|
|
44
|
+
r.get 'use_request_specific_token', :use do |use|
|
45
|
+
render :inline=>"[#{Base64.strict_encode64(send(:csrf_secret))}]<%= form({:method=>:post}, {:use_request_specific_token=>#{use == '1'}}) %>"
|
46
|
+
end
|
47
|
+
r.get 'csrf', :use do |use|
|
48
|
+
render :inline=>"<%= form({:method=>:post}, {:csrf=>#{use == '1'}}) %>"
|
49
|
+
end
|
50
|
+
instance_exec(r, &block)
|
46
51
|
end
|
47
|
-
instance_exec(r, &ERB_BLOCK)
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
@@ -54,7 +58,7 @@ rescue LoadError
|
|
54
58
|
warn "unable to load rack/csrf, skipping roda csrf plugin spec"
|
55
59
|
else
|
56
60
|
describe "Forme Roda ERB integration with roda forme and csrf plugins" do
|
57
|
-
app = FormeRodaCSRFTest =
|
61
|
+
app = FormeRodaCSRFTest = FormeRodaTest()
|
58
62
|
app.plugin :csrf
|
59
63
|
app.plugin :forme
|
60
64
|
|
@@ -68,64 +72,85 @@ describe "Forme Roda ERB integration with roda forme and csrf plugins" do
|
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
75
|
+
module FormeRouteCsrfSpecs
|
76
|
+
extend Minitest::Spec::DSL
|
77
|
+
include FormeErbSpecs
|
78
|
+
|
79
|
+
it "should have a valid CSRF tag" do
|
80
|
+
output = sin_get('/use_request_specific_token/1')
|
81
|
+
output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
|
82
|
+
secret = $1
|
83
|
+
token = $2
|
84
|
+
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/1', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal true
|
85
|
+
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/2', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal false
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should handle the :use_request_specific_token => true option" do
|
89
|
+
output = sin_get('/use_request_specific_token/1')
|
90
|
+
output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
|
91
|
+
secret = $1
|
92
|
+
token = $2
|
93
|
+
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/1', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal true
|
94
|
+
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/2', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal false
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should handle the :use_request_specific_token => false option" do
|
98
|
+
output = sin_get('/use_request_specific_token/0')
|
99
|
+
output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
|
100
|
+
secret = $1
|
101
|
+
token = $2
|
102
|
+
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/0', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal(plugin_opts.empty? ? false : true)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should handle the :csrf option" do
|
106
|
+
sin_get('/csrf/1').must_include '<input name="_csrf" type="hidden" value="'
|
107
|
+
sin_get('/csrf/0').wont_include '<input name="_csrf" type="hidden" value="'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
71
111
|
begin
|
72
112
|
require 'roda/plugins/route_csrf'
|
113
|
+
require 'roda/plugins/capture_erb'
|
114
|
+
require 'roda/plugins/inject_erb'
|
73
115
|
rescue LoadError
|
74
|
-
warn "unable to load
|
116
|
+
warn "unable to load necessary Roda plugins, skipping forme_erubi_capture plugin spec"
|
75
117
|
else
|
118
|
+
describe "Forme Roda Erubi::CaptureEnd integration with roda forme_route_csrf" do
|
119
|
+
app = FormeRodaTest(ERUBI_CAPTURE_BLOCK)
|
120
|
+
app.plugin :forme_erubi_capture
|
121
|
+
app.plugin :render, :engine_opts=>{'erb'=>{:engine_class=>Erubi::CaptureEndEngine}}
|
122
|
+
|
123
|
+
define_method(:app){app}
|
124
|
+
define_method(:plugin_opts){{}}
|
125
|
+
define_method(:sin_get) do |path|
|
126
|
+
s = String.new
|
127
|
+
app.call(@rack.merge('PATH_INFO'=>path))[2].each{|str| s << str}
|
128
|
+
s.gsub(/\s+/, ' ').strip
|
129
|
+
end
|
130
|
+
|
131
|
+
include FormeRouteCsrfSpecs
|
132
|
+
end if defined?(ERUBI_CAPTURE_BLOCK)
|
133
|
+
|
76
134
|
[{}, {:require_request_specific_tokens=>false}].each do |plugin_opts|
|
77
135
|
describe "Forme Roda ERB integration with roda forme_route_csrf and route_csrf plugin with #{plugin_opts}" do
|
78
|
-
app =
|
136
|
+
app = FormeRodaTest()
|
79
137
|
app.plugin :forme_route_csrf
|
80
138
|
app.plugin :route_csrf, plugin_opts
|
81
139
|
|
140
|
+
define_method(:app){app}
|
141
|
+
define_method(:plugin_opts){plugin_opts}
|
82
142
|
define_method(:sin_get) do |path|
|
83
143
|
s = String.new
|
84
144
|
app.call(@rack.merge('PATH_INFO'=>path))[2].each{|str| s << str}
|
85
145
|
s.gsub(/\s+/, ' ').strip
|
86
146
|
end
|
87
147
|
|
88
|
-
include
|
89
|
-
|
90
|
-
it "should handle the :hidden_tags option" do
|
91
|
-
output = sin_get('/use_request_specific_token/1')
|
92
|
-
output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
|
93
|
-
secret = $1
|
94
|
-
token = $2
|
95
|
-
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/1', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal true
|
96
|
-
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/2', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal false
|
97
|
-
end
|
98
|
-
|
99
|
-
it "should handle the :use_request_specific_token => true option" do
|
100
|
-
output = sin_get('/use_request_specific_token/1')
|
101
|
-
output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
|
102
|
-
secret = $1
|
103
|
-
token = $2
|
104
|
-
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/1', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal true
|
105
|
-
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/2', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal false
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should handle the :use_request_specific_token => false option" do
|
109
|
-
output = sin_get('/use_request_specific_token/0')
|
110
|
-
output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
|
111
|
-
secret = $1
|
112
|
-
token = $2
|
113
|
-
app.new({'SCRIPT_NAME'=>'', 'PATH_INFO'=>'/use_request_specific_token/0', 'REQUEST_METHOD'=>'POST', 'rack.session'=>{'_roda_csrf_secret'=>secret}, 'rack.input'=>StringIO.new}).valid_csrf?(:token=>token).must_equal(plugin_opts.empty? ? false : true)
|
114
|
-
end
|
115
|
-
|
116
|
-
it "should handle the :hidden_tags option" do
|
117
|
-
sin_get('/hidden_tags').must_include 'name="foo" type="hidden" value="bar"'
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should handle the :csrf option" do
|
121
|
-
sin_get('/csrf/1').must_include '<input name="_csrf" type="hidden" value="'
|
122
|
-
sin_get('/csrf/0').wont_include '<input name="_csrf" type="hidden" value="'
|
123
|
-
end
|
148
|
+
include FormeRouteCsrfSpecs
|
124
149
|
end
|
125
150
|
|
126
151
|
describe "Forme Roda ERB Sequel integration with roda forme_set plugin and route_csrf plugin with #{plugin_opts}" do
|
127
152
|
before do
|
128
|
-
@app =
|
153
|
+
@app = FormeRodaTest()
|
129
154
|
@app.plugin :route_csrf, plugin_opts
|
130
155
|
@app.plugin(:forme_set, :secret=>'1'*64)
|
131
156
|
|
@@ -149,11 +174,15 @@ else
|
|
149
174
|
forme_set_block = orig_hash.delete(:forme_set_block)
|
150
175
|
orig_hash.each{|k,v| hash[k.to_s] = v}
|
151
176
|
album = @ab
|
152
|
-
ret,
|
177
|
+
ret, _, data, hmac = nil
|
153
178
|
|
154
179
|
@app.route do |r|
|
155
180
|
r.get do
|
156
|
-
|
181
|
+
if @block = env[:block]
|
182
|
+
render(:inline=>'<% form(*env[:args]) do |f| %><%= @block.call(f) %><% end %>')
|
183
|
+
else
|
184
|
+
form(*env[:args])
|
185
|
+
end
|
157
186
|
end
|
158
187
|
r.post do
|
159
188
|
r.params.replace(env[:params])
|
@@ -173,6 +202,25 @@ else
|
|
173
202
|
end
|
174
203
|
meth == :forme_parse ? ret : h
|
175
204
|
end
|
205
|
+
|
206
|
+
it "should have subform work correctly" do
|
207
|
+
@app.route do |r|
|
208
|
+
@album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
|
209
|
+
@album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
|
210
|
+
erb <<END
|
211
|
+
0
|
212
|
+
<% form(@album, {:action=>'/baz'}, :button=>'Sub') do |f| %>
|
213
|
+
1
|
214
|
+
<%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo', :grid=>true, :labels=>%w'Name') %>
|
215
|
+
2
|
216
|
+
<% end %>
|
217
|
+
3
|
218
|
+
END
|
219
|
+
end
|
220
|
+
|
221
|
+
body = @app.call('REQUEST_METHOD'=>'GET')[2].join.gsub("\n", ' ').gsub(/ +/, ' ').chomp(' ')
|
222
|
+
body.sub(%r{<input name="_csrf" type="hidden" value="([^"]+)"/>}, '<input name="_csrf" type="hidden" value="csrf"/>').must_equal '0 <form action="/baz" class="forme album" method="post"><input name="_csrf" type="hidden" value="csrf"/> 1 <input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="2"/><table><caption>Foo</caption><thead><tr><th>Name</th></tr></thead><tbody><tr><td class="string"><input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="A"/></td></tr></tbody></table> 2 <input type="submit" value="Sub"/></form>3'
|
223
|
+
end
|
176
224
|
|
177
225
|
it "#forme_set should include HMAC values if form includes inputs for obj" do
|
178
226
|
h = forme_set(@ab, :name=>'Foo')
|
@@ -274,7 +322,7 @@ else
|
|
274
322
|
obj.must_be_same_as @ab
|
275
323
|
version.must_be_nil
|
276
324
|
|
277
|
-
|
325
|
+
forme_set(@ab, {:name=>'Bar', :forme_set_block=>forme_set_block}, {}, :form_version=>2){|f| f.input(:name)}
|
278
326
|
obj.must_be_same_as @ab
|
279
327
|
name.must_equal 'Bar'
|
280
328
|
version.must_equal 2
|
data/spec/sequel_helper.rb
CHANGED
data/spec/sequel_i18n_helper.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
2
|
|
3
3
|
begin
|
4
|
-
|
4
|
+
raise LoadError if defined?(JRUBY_VERSION) && /\A9\.2\./.match(JRUBY_VERSION)
|
5
|
+
require_relative 'sequel_i18n_helper'
|
5
6
|
rescue LoadError
|
6
7
|
warn "unable to load i18n, skipping i18n Sequel plugin spec"
|
7
8
|
else
|
data/spec/sequel_plugin_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require_relative 'sequel_helper'
|
3
3
|
|
4
4
|
describe "Forme Sequel::Model forms" do
|
5
5
|
before do
|
@@ -9,6 +9,15 @@ describe "Forme Sequel::Model forms" do
|
|
9
9
|
@c = Forme::Form.new(@ac)
|
10
10
|
end
|
11
11
|
|
12
|
+
it "should handle Forme::Form subclasses" do
|
13
|
+
c = Class.new(Forme::Form) do
|
14
|
+
def form(*)
|
15
|
+
super{|f| f.tag(:input, :type=>:hidden, :name=>'a', :value=>'b')}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
c.new(@ab).form.to_s.must_equal '<form class="forme album" method="post"><input name="a" type="hidden" value="b"/></form>'
|
19
|
+
end
|
20
|
+
|
12
21
|
it "should add appropriate attributes by default" do
|
13
22
|
@b.form.to_s.must_equal '<form class="forme album" method="post"></form>'
|
14
23
|
end
|
@@ -331,6 +340,11 @@ describe "Forme Sequel::Model forms" do
|
|
331
340
|
@b.input(:foo, :type=>:phone).to_s.must_equal '<label>Foo: <input id="album_foo" name="album[foo]" type="phone" value="bar"/></label>'
|
332
341
|
end
|
333
342
|
|
343
|
+
it "should not override an explicit :error setting" do
|
344
|
+
@ab.errors.add(:name, 'tis not valid')
|
345
|
+
@b.input(:name, :error=>nil).to_s.must_equal '<label>Name: <input id="album_name" maxlength="255" name="album[name]" type="text" value="b"/></label>'
|
346
|
+
end
|
347
|
+
|
334
348
|
it "should correctly show an error message if there is one" do
|
335
349
|
@ab.errors.add(:name, 'tis not valid')
|
336
350
|
@b.input(:name).to_s.must_equal '<label>Name: <input aria-describedby="album_name_error_message" aria-invalid="true" class="error" id="album_name" maxlength="255" name="album[name]" type="text" value="b"/></label><span class="error_message" id="album_name_error_message">tis not valid</span>'
|
@@ -400,19 +414,19 @@ describe "Forme Sequel::Model forms" do
|
|
400
414
|
end
|
401
415
|
|
402
416
|
it "should use allow nested forms with one_to_many associations" do
|
403
|
-
Forme.form(@ab){|f| f.subform(:tracks){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Track #1</legend><label>Name: <input id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></label></fieldset><
|
417
|
+
Forme.form(@ab){|f| f.subform(:tracks){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #1</legend><label>Name: <input id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></label></fieldset><fieldset class="inputs"><legend>Track #2</legend><label>Name: <input id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></label></fieldset></form>'
|
404
418
|
end
|
405
419
|
|
406
420
|
it "should support :obj option for *_to_many associations" do
|
407
|
-
Forme.form(@ab){|f| f.subform(:tracks, :obj=>[Track.new(:name=>'x'), Track.load(:id=>5, :name=>'y')]){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><fieldset class="inputs"><legend>Track #1</legend><label>Name: <input id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="x"/></label></fieldset><
|
421
|
+
Forme.form(@ab){|f| f.subform(:tracks, :obj=>[Track.new(:name=>'x'), Track.load(:id=>5, :name=>'y')]){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="5"/><fieldset class="inputs"><legend>Track #1</legend><label>Name: <input id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="x"/></label></fieldset><fieldset class="inputs"><legend>Track #2</legend><label>Name: <input id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="y"/></label></fieldset></form>'
|
408
422
|
end
|
409
423
|
|
410
424
|
it "should auto number legends when using subform with inputs for *_to_many associations" do
|
411
|
-
Forme.form(@ab){|f| f.subform(:tracks, :inputs=>[:name])}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Track #1</legend><label>Name: <input id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></label></fieldset><
|
425
|
+
Forme.form(@ab){|f| f.subform(:tracks, :inputs=>[:name])}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #1</legend><label>Name: <input id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></label></fieldset><fieldset class="inputs"><legend>Track #2</legend><label>Name: <input id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></label></fieldset></form>'
|
412
426
|
end
|
413
427
|
|
414
428
|
it "should support callable :legend option when using subform with inputs for *_to_many associations" do
|
415
|
-
Forme.form(@ab){|f| f.subform(:tracks, :inputs=>[:name], :legend=>proc{|o, i| "Track #{i} (#{o.name})"})}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Track 0 (m)</legend><label>Name: <input id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></label></fieldset><
|
429
|
+
Forme.form(@ab){|f| f.subform(:tracks, :inputs=>[:name], :legend=>proc{|o, i| "Track #{i} (#{o.name})"})}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track 0 (m)</legend><label>Name: <input id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></label></fieldset><fieldset class="inputs"><legend>Track 1 (n)</legend><label>Name: <input id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></label></fieldset></form>'
|
416
430
|
end
|
417
431
|
|
418
432
|
it "should not add hidden primary key field for nested forms with one_to_many associations with new objects" do
|
@@ -421,7 +435,7 @@ describe "Forme Sequel::Model forms" do
|
|
421
435
|
end
|
422
436
|
|
423
437
|
it "should use allow nested forms with many_to_many associations" do
|
424
|
-
Forme.form(@ab){|f| f.subform(:tags){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tags_attributes_0_id" name="album[tags_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Tag #1</legend><label>Name: <input id="album_tags_attributes_0_name" maxlength="255" name="album[tags_attributes][0][name]" type="text" value="s"/></label></fieldset><
|
438
|
+
Forme.form(@ab){|f| f.subform(:tags){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tags_attributes_0_id" name="album[tags_attributes][0][id]" type="hidden" value="1"/><input id="album_tags_attributes_1_id" name="album[tags_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Tag #1</legend><label>Name: <input id="album_tags_attributes_0_name" maxlength="255" name="album[tags_attributes][0][name]" type="text" value="s"/></label></fieldset><fieldset class="inputs"><legend>Tag #2</legend><label>Name: <input id="album_tags_attributes_1_name" maxlength="255" name="album[tags_attributes][1][name]" type="text" value="t"/></label></fieldset></form>'
|
425
439
|
end
|
426
440
|
|
427
441
|
it "should not add hidden primary key field for nested forms with many_to_many associations with new objects" do
|
@@ -430,29 +444,32 @@ describe "Forme Sequel::Model forms" do
|
|
430
444
|
end
|
431
445
|
|
432
446
|
it "should handle multiple nested levels" do
|
433
|
-
Forme.form(Artist[1]){|f| f.subform(:albums){f.input(:name); f.subform(:tracks){f.input(:name)}}}.to_s.to_s.must_equal '<form class="forme artist" method="post"><input id="artist_albums_attributes_0_id" name="artist[albums_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Album #1</legend><label>Name: <input id="artist_albums_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][name]" type="text" value="b"/></label><input id="artist_albums_attributes_0_tracks_attributes_0_id" name="artist[albums_attributes][0][tracks_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Track #1</legend><label>Name: <input id="artist_albums_attributes_0_tracks_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][tracks_attributes][0][name]" type="text" value="m"/></label></fieldset><
|
447
|
+
Forme.form(Artist[1]){|f| f.subform(:albums){f.input(:name); f.subform(:tracks){f.input(:name)}}}.to_s.to_s.must_equal '<form class="forme artist" method="post"><input id="artist_albums_attributes_0_id" name="artist[albums_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Album #1</legend><label>Name: <input id="artist_albums_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][name]" type="text" value="b"/></label><input id="artist_albums_attributes_0_tracks_attributes_0_id" name="artist[albums_attributes][0][tracks_attributes][0][id]" type="hidden" value="1"/><input id="artist_albums_attributes_0_tracks_attributes_1_id" name="artist[albums_attributes][0][tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #1</legend><label>Name: <input id="artist_albums_attributes_0_tracks_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][tracks_attributes][0][name]" type="text" value="m"/></label></fieldset><fieldset class="inputs"><legend>Track #2</legend><label>Name: <input id="artist_albums_attributes_0_tracks_attributes_1_name" maxlength="255" name="artist[albums_attributes][0][tracks_attributes][1][name]" type="text" value="n"/></label></fieldset></fieldset></form>'
|
434
448
|
end
|
435
449
|
|
436
450
|
it "should have #subform :grid option create a grid" do
|
437
|
-
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true)}.to_s.must_equal '<form class="forme album" method="post"><
|
451
|
+
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true)}.to_s.must_equal '<form class="forme album" method="post"><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><table><caption>Artist</caption><thead><tr><th>Name</th></tr></thead><tbody><tr><td class="string"><input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
|
438
452
|
end
|
439
453
|
|
440
454
|
it "should have #subform :grid option respect :inputs_opts option to pass options to inputs" do
|
441
|
-
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :inputs_opts=>{:attr=>{:class=>'foo'}})}.to_s.must_equal '<form class="forme album" method="post"><
|
455
|
+
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :inputs_opts=>{:attr=>{:class=>'foo'}})}.to_s.must_equal '<form class="forme album" method="post"><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><table class="foo"><caption>Artist</caption><thead><tr><th>Name</th></tr></thead><tbody><tr><td class="string"><input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
|
442
456
|
end
|
443
457
|
|
444
458
|
it "should have #subform :grid option handle :legend and :labels options" do
|
445
|
-
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :legend=>'Foo', :labels=>%w'Bar')}.to_s.must_equal '<form class="forme album" method="post"><
|
459
|
+
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :legend=>'Foo', :labels=>%w'Bar')}.to_s.must_equal '<form class="forme album" method="post"><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><table><caption>Foo</caption><thead><tr><th>Bar</th></tr></thead><tbody><tr><td class="string"><input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
|
446
460
|
end
|
447
461
|
|
448
462
|
it "should have #subform :grid option handle :legend and :labels nil values" do
|
449
|
-
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :legend=>nil, :labels=>nil)}.to_s.must_equal '<form class="forme album" method="post"><
|
463
|
+
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :legend=>nil, :labels=>nil)}.to_s.must_equal '<form class="forme album" method="post"><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><table><tbody><tr><td class="string"><input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
|
450
464
|
end
|
451
465
|
|
452
466
|
it "should have #subform :grid option handle :skip_primary_key option" do
|
453
467
|
Forme.form(@ab){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :skip_primary_key=>true)}.to_s.must_equal '<form class="forme album" method="post"><table><caption>Artist</caption><thead><tr><th>Name</th></tr></thead><tbody><tr><td class="string"><input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
|
454
468
|
end
|
455
469
|
|
470
|
+
it "should handle non-Sequel forms with Sequel inputs" do
|
471
|
+
Forme.form{|f| f.input(:name, :obj=>@ab).to_s.must_equal '<label>Name: <input id="name" maxlength="255" name="name" type="text" value="b"/></label>'}
|
472
|
+
end
|
456
473
|
end
|
457
474
|
|
458
475
|
describe "Forme Sequel plugin default input types based on column names" do
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require_relative 'sequel_helper'
|
3
3
|
|
4
4
|
describe "Sequel forme_set plugin" do
|
5
5
|
before do
|
@@ -222,4 +222,11 @@ describe "Sequel forme_set plugin" do
|
|
222
222
|
@ab.forme_validations[:name] = [:bar, []]
|
223
223
|
proc{@ab.valid?}.must_raise Sequel::Plugins::Forme::Error
|
224
224
|
end
|
225
|
+
|
226
|
+
it "should handle frozen instances as form inputs" do
|
227
|
+
@ab.freeze
|
228
|
+
@ab.forme_inputs.must_equal({})
|
229
|
+
@ab.forme_validations.must_equal({})
|
230
|
+
@f.input(:name).must_equal '<label>Name: <input id="album_name" maxlength="255" name="album[name]" type="text"/></label>'
|
231
|
+
end
|
225
232
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module FormeErbSpecs
|
2
|
+
extend Minitest::Spec::DSL
|
3
|
+
|
4
|
+
before do
|
5
|
+
o = Object.new
|
6
|
+
def o.puts(*) end
|
7
|
+
@rack = {'rack.input'=>'', 'REQUEST_METHOD'=>'GET', 'rack.errors'=>o, 'SCRIPT_NAME'=>''}
|
8
|
+
end
|
9
|
+
|
10
|
+
it "#form should add start and end tags and yield Forme::Form instance" do
|
11
|
+
sin_get('/').must_equal '<form action="/baz"> <p>FBB</p> <input id="first" name="first" type="text" value="foo"/> <input id="last" name="last" type="text" value="bar"/> <input type="submit" value="Save"/> </form>'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "#form should have inputs work with a block" do
|
15
|
+
sin_get('/inputs_block').must_equal '<form action="/baz"><fieldset class="inputs"><legend>FBB</legend> <input id="last" name="last" type="text" value="bar"/> </fieldset></form>'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "#form should have inputs with fieldset_ol wrapper work with block" do
|
19
|
+
sin_get('/inputs_block_wrapper').must_equal '<form action="/baz"><fieldset class="inputs"><legend>FBB</legend><ol> <input id="last" name="last" type="text" value="bar"/> </ol></fieldset></form>'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "#form should add start and end tags and yield Forme::Form instance" do
|
23
|
+
sin_get('/nest').must_equal '<form action="/baz"> <p>FBB</p> <div> <input id="first" name="first" type="text" value="foo"/> <input id="last" name="last" type="text" value="bar"/> </div> </form>'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "#form should correctly handle situation where multiple templates are used with same form object" do
|
27
|
+
sin_get('/nest_sep').sub(/ 4\z/, '4').must_equal '0 <form action="/baz"> 1 <p>FBB</p> 2 n1 <div> n2 <input id="first" name="first" type="text" value="foo"/> <input id="last" name="last" type="text" value="bar"/> n3 </div> n4 <fieldset class="inputs"><legend>Foo</legend><input id="first" name="first" type="text" value="foo"/><input id="last" name="last" type="text" value="bar"/></fieldset> n5 3 </form>4'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "#form should correctly handle situation Sequel integration with subforms where multiple templates are used with same form object" do
|
31
|
+
sin_get('/nest_seq_simple').sub(/ 4\z/, '4').sub(%r{<input name="_csrf" type="hidden" value="([^"]+)"/>}, '<input name="_csrf" type="hidden" value="csrf"/>').must_equal '0 <form action="/baz" class="forme album" method="post"><input name="_csrf" type="hidden" value="csrf"/> 1 n1 <input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Artist</legend> n2 <label>Name2: <input id="album_artist_attributes_name2" name="album[artist_attributes][name2]" type="text" value="A2"/></label> n3 </fieldset> n4 3 </form>4'
|
32
|
+
|
33
|
+
sin_get('/nest_seq').sub(/ 4\z/, '4').sub(%r{<input name="_csrf" type="hidden" value="([^"]+)"/>}, '<input name="_csrf" type="hidden" value="csrf"/>').must_equal '0 <form action="/baz" class="forme album" method="post"><input name="_csrf" type="hidden" value="csrf"/> 1 <input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Foo</legend><label>Name: <input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="A"/></label></fieldset> 2 n1 <input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Artist</legend> n2 <label>Name2: <input id="album_artist_attributes_name2" name="album[artist_attributes][name2]" type="text" value="A2"/></label> n3 </fieldset> n4 <input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Bar</legend><label>Name3: <input id="album_artist_attributes_name3" name="album[artist_attributes][name3]" type="text" value="A3"/></label></fieldset> n5 3 </form>4'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "#form should correctly handle subform with :grid option with block" do
|
37
|
+
sin_get('/grid-block').sub(/ 4\z/, '4').sub(%r{<input name="_csrf" type="hidden" value="([^"]+)"/>}, '<input name="_csrf" type="hidden" value="csrf"/>').must_equal '0 <form action="/baz" class="forme album" method="post"><input name="_csrf" type="hidden" value="csrf"/> 1 <input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="2"/><table><caption>Foo</caption><thead><tr><th>Name</th></tr></thead><tbody><tr><td class="string"><input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="A"/></td> 2 </tr></tbody></table> 3 <input type="submit" value="Sub"/></form>4'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "#form should correctly handle subform with :grid option without block" do
|
41
|
+
sin_get('/grid-noblock').sub(/ 3\z/, '3').sub(%r{<input name="_csrf" type="hidden" value="([^"]+)"/>}, '<input name="_csrf" type="hidden" value="csrf"/>').must_equal '0 <form action="/baz" class="forme album" method="post"><input name="_csrf" type="hidden" value="csrf"/> 1 <input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="2"/><table><caption>Foo</caption><thead><tr><th>Name</th></tr></thead><tbody><tr><td class="string"><input id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="A"/></td></tr></tbody></table> 2 <input type="submit" value="Sub"/></form>3'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "#form should correctly handle subform with :grid option without block" do
|
45
|
+
sin_get('/grid-noblock-multiple').sub(/ 3\z/, '3').sub(%r{<input name="_csrf" type="hidden" value="([^"]+)"/>}, '<input name="_csrf" type="hidden" value="csrf"/>').must_equal '0 <form action="/baz" class="forme artist" method="post"><input name="_csrf" type="hidden" value="csrf"/> 1 <input id="artist_albums_attributes_0_id" name="artist[albums_attributes][0][id]" type="hidden" value="1"/><table><caption>Foo</caption><thead><tr><th>Name</th><th>Copies</th></tr></thead><tbody><tr><td class="string"><input id="artist_albums_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][name]" type="text" value="N"/></td><td class="integer"><input id="artist_albums_attributes_0_copies_sold" name="artist[albums_attributes][0][copies_sold]" type="number" value="2"/></td></tr></tbody></table> 2 <input type="submit" value="Sub"/></form>3'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "#form should accept two hashes instead of requiring obj as first argument" do
|
49
|
+
sin_get('/hash').must_equal '<form action="/baz"> <input id="first" name="first" type="text" value="foo"/> </form>'
|
50
|
+
end
|
51
|
+
|
52
|
+
it "#form should deal with emitted code" do
|
53
|
+
sin_get('/legend').must_equal '<form action="/baz"> <p>FBB</p> <fieldset class="inputs"><legend>Foo</legend><input id="first" name="first" type="text" value="foo"/><input id="last" name="last" type="text" value="bar"/></fieldset> <p>FBB2</p> </form>'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "#form should work with :inputs, :button, and :legend options" do
|
57
|
+
sin_get('/combined').must_equal '<form action="/baz"><fieldset class="inputs"><legend>123</legend><input id="first" name="first" type="text" value="foo"/></fieldset> <p>FBB</p> <input id="last" name="last" type="text" value="bar"/> <input type="submit" value="xyz"/></form>'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "#form should work without a block" do
|
61
|
+
sin_get('/noblock').must_equal '<form action="/baz"><fieldset class="inputs"><legend>123</legend><input id="first" name="first" type="text" value="foo"/></fieldset><input type="submit" value="xyz"/></form>'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "#form should work without a block and still have hidden tags emitted" do
|
65
|
+
sin_get('/noblock_post').sub(%r{<input name=\"_csrf\" type=\"hidden\" value=\"([^\"]+)\"/>}, "<input name=\"_csrf\" type=\"hidden\" value=\"csrf\"/>").must_equal '<form method="post"><input name="_csrf" type="hidden" value="csrf"/><input type="submit" value="xyz"/></form>'
|
66
|
+
end
|
67
|
+
|
68
|
+
it "#form with an empty form should work" do
|
69
|
+
sin_get('/noblock_empty').must_equal '<form action="/baz"></form>'
|
70
|
+
end
|
71
|
+
end
|
@@ -1,8 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require_relative 'sequel_helper'
|
3
|
+
require_relative 'erb_helper'
|
4
4
|
|
5
|
-
require 'rubygems'
|
6
5
|
begin
|
7
6
|
require 'sinatra/base'
|
8
7
|
require 'rack/csrf'
|
@@ -19,9 +18,9 @@ rescue LoadError
|
|
19
18
|
require 'erb'
|
20
19
|
end
|
21
20
|
end
|
22
|
-
|
21
|
+
require_relative '../lib/forme/erb'
|
23
22
|
class FormeSinatraTest < Sinatra::Base
|
24
|
-
helpers(Forme::
|
23
|
+
helpers(Forme::ERB::Helper)
|
25
24
|
disable :show_exceptions
|
26
25
|
enable :raise_errors
|
27
26
|
enable :sessions
|
data/spec/spec_helper.rb
CHANGED
@@ -1,18 +1,31 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'lib'))
|
2
2
|
|
3
|
-
if ENV['WARNING']
|
4
|
-
require 'warning'
|
5
|
-
Warning.ignore([:missing_ivar, :not_reached])
|
6
|
-
end
|
7
|
-
|
8
3
|
if ENV['COVERAGE']
|
9
|
-
|
4
|
+
require_relative 'forme_coverage'
|
10
5
|
SimpleCov.forme_coverage
|
11
6
|
end
|
12
7
|
|
13
|
-
|
8
|
+
require_relative '../lib/forme'
|
14
9
|
|
15
|
-
require 'rubygems'
|
16
10
|
ENV['MT_NO_PLUGINS'] = '1' # Work around stupid autoloading of plugins
|
17
11
|
gem 'minitest'
|
18
12
|
require 'minitest/global_expectations/autorun'
|
13
|
+
|
14
|
+
module Minitest::Spec::DSL
|
15
|
+
def silence_warnings(name, &block)
|
16
|
+
it(name) do
|
17
|
+
silence_warnings do
|
18
|
+
instance_exec(&block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Minitest::Spec
|
25
|
+
def silence_warnings
|
26
|
+
verbose, $VERBOSE = $VERBOSE, nil
|
27
|
+
yield
|
28
|
+
ensure
|
29
|
+
$VERBOSE = verbose
|
30
|
+
end
|
31
|
+
end
|