forme 1.12.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,202 @@
1
+ require_relative 'shared_erb_specs'
2
+
3
+ ERUBI_CAPTURE_BLOCK = lambda do |r|
4
+ r.get '' do
5
+ erb <<END
6
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %>
7
+ <p>FBB</p>
8
+ <%= f.input(:first) %>
9
+ <%= f.input(:last) %>
10
+ <%= f.button('Save') %>
11
+ <%| end %>
12
+ END
13
+ end
14
+
15
+ r.get 'inputs_block' do
16
+ erb <<END
17
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %><%|= f.inputs(:legend=>'FBB') do %>
18
+ <%= f.input(:last) %>
19
+ <%| end %><%| end %>
20
+ END
21
+ end
22
+
23
+ r.get 'inputs_block_wrapper' do
24
+ erb <<END
25
+ <%|= form([:foo, :bar], {:action=>'/baz'}, :inputs_wrapper=>:fieldset_ol) do |f| %><%|= f.inputs(:legend=>'FBB') do %>
26
+ <%= f.input(:last) %>
27
+ <%| end %><%| end %>
28
+ END
29
+ end
30
+
31
+ r.get 'nest' do
32
+ erb <<END
33
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %>
34
+ <%= f.tag(:p, {}, 'FBB') %>
35
+ <%|= f.tag(:div) do %>
36
+ <%= f.input(:first) %>
37
+ <%= f.input(:last) %>
38
+ <%| end %>
39
+
40
+ <%| end %>
41
+ END
42
+ end
43
+
44
+ r.get 'nest_sep' do
45
+ @nest = <<END
46
+ n1
47
+ <%|= f.tag(:div) do %>
48
+ n2
49
+ <%= f.input(:first) %>
50
+ <%= f.input(:last) %>
51
+ n3
52
+ <%| end %>
53
+ n4
54
+ <%= f.inputs([:first, :last], :legend=>'Foo') %>
55
+ n5
56
+ END
57
+ erb <<END
58
+ 0
59
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %>
60
+ 1
61
+ <%= f.tag(:p, {}, 'FBB') %>
62
+ 2
63
+ <%= erb(@nest, :locals=>{:f=>f}) %>
64
+ 3
65
+ <%| end %>
66
+ 4
67
+ END
68
+ end
69
+
70
+ r.get 'nest_seq_simple' do
71
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
72
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
73
+ @nest = <<END
74
+ n1
75
+ <%|= f.subform(:artist) do %>
76
+ n2
77
+ <%= f.input(:name2) %>
78
+ n3
79
+ <%| end %>
80
+ n4
81
+ END
82
+ erb <<END
83
+ 0
84
+ <%|= form(@album, :action=>'/baz') do |f| %>
85
+ 1
86
+ <%= erb(@nest, :locals=>{:f=>f}) %>
87
+ 3
88
+ <%| end %>
89
+ 4
90
+ END
91
+ end
92
+
93
+ r.get 'nest_seq' do
94
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
95
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
96
+ @nest = <<END
97
+ n1
98
+ <%|= f.subform(:artist) do %>
99
+ n2
100
+ <%= f.input(:name2) %>
101
+ n3
102
+ <%| end %>
103
+ n4
104
+ <%= f.subform(:artist, :inputs=>[:name3], :legend=>'Bar') %>
105
+ n5
106
+ END
107
+ erb <<END
108
+ 0
109
+ <%|= form(@album, :action=>'/baz') do |f| %>
110
+ 1
111
+ <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo') %>
112
+ 2
113
+ <%= erb(@nest, :locals=>{:f=>f}) %>
114
+ 3
115
+ <%| end %>
116
+ 4
117
+ END
118
+ end
119
+
120
+ r.get 'grid-block' do
121
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
122
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
123
+ erb <<END
124
+ 0
125
+ <%|= form(@album, {:action=>'/baz'}, :button=>'Sub') do |f| %>
126
+ 1
127
+ <%|= f.subform(:artist, :inputs=>[:name], :legend=>'Foo', :grid=>true, :labels=>%w'Name') do %>
128
+ 2
129
+ <%| end %>
130
+ 3
131
+ <%| end %>
132
+ 4
133
+ END
134
+ end
135
+
136
+ r.get 'grid-noblock' do
137
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
138
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
139
+ erb <<END
140
+ 0
141
+ <%|= form(@album, {:action=>'/baz'}, :button=>'Sub') do |f| %>
142
+ 1
143
+ <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo', :grid=>true, :labels=>%w'Name') %>
144
+ 2
145
+ <%| end %>
146
+ 3
147
+ END
148
+ end
149
+
150
+ r.get 'grid-noblock-multiple' do
151
+ @artist = Artist.load(:name=>'A', :id=>2)
152
+ @artist.associations[:albums] = [Album.load(:name=>'N', :copies_sold=>2, :id=>1)]
153
+ erb <<END
154
+ 0
155
+ <%|= form(@artist, {:action=>'/baz'}, :button=>'Sub') do |f| %>
156
+ 1
157
+ <%= f.subform(:albums, :inputs=>[:name, :copies_sold], :legend=>'Foo', :grid=>true, :labels=>%w'Name Copies') %>
158
+ 2
159
+ <%| end %>
160
+ 3
161
+ END
162
+ end
163
+
164
+ r.get 'hash' do
165
+ erb "<%|= form({:action=>'/baz'}, :obj=>[:foo]) do |f| %> <%= f.input(:first) %> <%| end %>"
166
+ end
167
+
168
+ r.get 'legend' do
169
+ erb <<END
170
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %>
171
+ <p>FBB</p>
172
+ <%= f.inputs([:first, :last], :legend=>'Foo') %>
173
+ <p>FBB2</p>
174
+ <%| end %>
175
+ END
176
+ end
177
+
178
+ r.get 'combined' do
179
+ erb <<END
180
+ <%|= form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') do |f| %>
181
+ <p>FBB</p>
182
+ <%= f.input(:last) %>
183
+ <%| end %>
184
+ END
185
+ end
186
+
187
+ r.get 'hidden_tags' do
188
+ erb "<%= form([:foo, :bar], {:action=>'/baz'}, :hidden_tags=>[{'a'=>'b'}]) %>"
189
+ end
190
+
191
+ r.get 'noblock' do
192
+ erb "<%= form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') %>"
193
+ end
194
+
195
+ r.get 'noblock_post' do
196
+ erb "<%= form({:method=>:post}, :button=>'xyz') %>"
197
+ end
198
+
199
+ r.get 'noblock_empty' do
200
+ erb "<%= form(:action=>'/baz') %>"
201
+ end
202
+ end
data/spec/forme_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
1
+ require_relative 'spec_helper'
2
2
 
3
3
  describe "Forme plain forms" do
4
4
  def sel(opts, s)
@@ -631,13 +631,19 @@ describe "Forme plain forms" do
631
631
  @f.tag(:textarea, {:name=>:foo}, :bar).to_s.must_equal '<textarea name="foo">bar</textarea>'
632
632
  end
633
633
 
634
+ it "#tag should accept a block" do
635
+ @f.tag(:div){@f.tag(:textarea)}.to_s.must_equal '<div><textarea></textarea></div>'
636
+ @f.tag(:div, :name=>'a'){@f.tag(:textarea)}.to_s.must_equal '<div name="a"><textarea></textarea></div>'
637
+ @f.tag(:div, {:name=>'a'}, ["text"]){@f.tag(:textarea)}.to_s.must_equal '<div name="a">text<textarea></textarea></div>'
638
+ end
639
+
634
640
  it "#tag should accept children as procs" do
635
- @f.tag(:div, {:class=>"foo"}, lambda{|t| t.form.tag(:input, :class=>t.attr[:class])}).to_s.must_equal '<div class="foo"><input class="foo"/></div>'
641
+ @f.tag(:div, {:class=>"foo"}, lambda{|t| t.tag(:input, :class=>t.attr[:class])}).to_s.must_equal '<div class="foo"><input class="foo"/></div>'
636
642
  end
637
643
 
638
644
  it "#tag should accept children as methods" do
639
645
  o = Object.new
640
- def o.foo(t) t.form.tag(:input, :class=>t.attr[:class]) end
646
+ def o.foo(t) t.tag(:input, :class=>t.attr[:class]) end
641
647
  @f.tag(:div, {:class=>"foo"}, o.method(:foo)).to_s.must_equal '<div class="foo"><input class="foo"/></div>'
642
648
  end
643
649
 
@@ -645,6 +651,10 @@ describe "Forme plain forms" do
645
651
  @f.inputs([:textarea, :text]).to_s.must_equal '<fieldset class="inputs"><textarea></textarea><input type="text"/></fieldset>'
646
652
  end
647
653
 
654
+ it "should have an #inputs method for multiple inputs wrapped in a fieldset when using an empty block" do
655
+ @f.inputs([:textarea, :text]){}.to_s.must_equal '<fieldset class="inputs"><textarea></textarea><input type="text"/></fieldset>'
656
+ end
657
+
648
658
  it "should have default #inputs method accept an :attr option" do
649
659
  @f.inputs([:textarea, :text], :legend=>'Inputs', :attr=>{:class=>'foo', :bar=>'baz'}).to_s.must_equal '<fieldset bar="baz" class="foo inputs"><legend>Inputs</legend><textarea></textarea><input type="text"/></fieldset>'
650
660
  end
@@ -805,41 +815,45 @@ describe "Forme plain forms" do
805
815
  proc{@f.input(:textarea, :wrapper=>Object.new).to_s}.must_raise(Forme::Error)
806
816
  proc{@f.input(:textarea, :formatter=>nil).to_s}.must_raise(Forme::Error)
807
817
  end
808
- end
809
818
 
810
- describe "Forme::Form :hidden_tags option " do
811
- before do
812
- @f = Forme::Form.new
819
+ it "should handle :before and :after hook options" do
820
+ Forme.form({}, :before=>lambda{|f| f.tag(:input, :type=>:hidden, :name=>:a, :value=>'b')}, :after=>lambda{|f| f.tag(:input, :type=>:hidden, :name=>:c, :value=>'d')}){|f| f.tag(:input)}.to_s.must_equal '<form><input name="a" type="hidden" value="b"/><input/><input name="c" type="hidden" value="d"/></form>'
813
821
  end
822
+ end
814
823
 
815
- it "should handle hash" do
824
+ describe "Forme::Form :hidden_tags option " do
825
+ silence_warnings "should handle hash" do
816
826
  Forme.form({}, :hidden_tags=>[{:a=>'b'}]).to_s.must_equal '<form><input name="a" type="hidden" value="b"/></form>'
817
827
  end
818
828
 
819
- it "should handle array" do
829
+ silence_warnings "should handle array" do
820
830
  Forme.form({}, :hidden_tags=>[["a ", "b"]]).to_s.must_equal '<form>a b</form>'
821
831
  end
822
832
 
823
- it "should handle string" do
833
+ silence_warnings "should handle string" do
824
834
  Forme.form({}, :hidden_tags=>["a "]).to_s.must_equal '<form>a </form>'
825
835
  end
826
836
 
827
- it "should handle proc return hash" do
837
+ silence_warnings "should handle proc return hash" do
828
838
  Forme.form({}, :hidden_tags=>[lambda{|tag| {:a=>'b'}}]).to_s.must_equal '<form><input name="a" type="hidden" value="b"/></form>'
829
839
  end
830
840
 
831
- it "should handle proc return tag" do
832
- Forme.form({:method=>'post'}, :hidden_tags=>[lambda{|tag| tag.form._tag(tag.attr[:method])}]).to_s.must_equal '<form method="post"><post></post></form>'
841
+ silence_warnings "should handle proc return hash when from takes a block" do
842
+ Forme.form({}, :hidden_tags=>[lambda{|tag| {:a=>'b'}}]){}.to_s.must_equal '<form><input name="a" type="hidden" value="b"/></form>'
843
+ end
844
+
845
+ silence_warnings "should handle proc return tag" do
846
+ Forme.form({:method=>'post'}, :hidden_tags=>[lambda{|tag| tag.tag(tag.attr[:method])}]).to_s.must_equal '<form method="post"><post></post></form>'
833
847
  end
834
848
 
835
- it "should raise error for unhandled object" do
849
+ silence_warnings "should raise error for unhandled object" do
836
850
  proc{Forme.form({}, :hidden_tags=>[Object.new])}.must_raise Forme::Error
837
851
  end
838
852
  end
839
853
 
840
854
  describe "Forme custom" do
841
855
  it "formatters can be specified as a proc" do
842
- Forme::Form.new(:formatter=>proc{|i| i.form._tag(:textarea, i.opts[:name]=>:name)}).input(:text, :name=>'foo').to_s.must_equal '<textarea foo="name"></textarea>'
856
+ Forme::Form.new(:formatter=>proc{|i| i.tag(:textarea, i.opts[:name]=>:name)}).input(:text, :name=>'foo').to_s.must_equal '<textarea foo="name"></textarea>'
843
857
  end
844
858
 
845
859
  it "serializers can be specified as a proc" do
@@ -1056,6 +1070,7 @@ describe "Forme built-in custom" do
1056
1070
  Forme::Form.new(:serializer=>:text).button().to_s.must_equal ""
1057
1071
  Forme::Form.new(:serializer=>:text).inputs([[:textarea, {:label=>"Foo", :value=>"Bar"}]], :legend=>'Baz').to_s.must_equal "Baz\n---\nFoo: Bar\n\n"
1058
1072
  Forme::Form.new(:serializer=>:text).tag(:p){|f| f.input(:textarea, :label=>"Foo", :value=>"Bar")}.to_s.must_equal "Foo: Bar\n\n"
1073
+ Forme::Form.new(:serializer=>:text).tag(:p, {}, ['a']).to_s.must_equal "a"
1059
1074
  end
1060
1075
  end
1061
1076
 
@@ -1,7 +1,6 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
- require File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_helper.rb')
1
+ require_relative 'spec_helper'
2
+ require_relative 'sequel_helper'
3
3
 
4
- require 'rubygems'
5
4
  begin
6
5
  require 'action_controller/railtie'
7
6
 
@@ -9,23 +8,22 @@ begin
9
8
  require 'active_pack/gem_version'
10
9
  rescue LoadError
11
10
  end
12
- require 'forme/rails'
11
+ require_relative '../lib/forme/rails'
13
12
 
14
13
  if Rails.respond_to?(:version) && Rails.version.start_with?('4')
15
14
  # Work around issue in backported openssl environments where
16
15
  # secret is 64 bytes intead of 32 bytes
17
16
  require 'active_support/message_encryptor'
18
- ActiveSupport::MessageEncryptor.send :prepend, Module.new {
19
- def initialize(secret, *signature_key_or_options)
20
- secret = secret[0, 32]
21
- super
22
- end
23
- }
17
+ def (ActiveSupport::MessageEncryptor).new(secret, *signature_key_or_options)
18
+ obj = allocate
19
+ obj.send(:initialize, secret[0, 32], *signature_key_or_options)
20
+ obj
21
+ end
24
22
  end
25
23
 
26
24
  class FormeRails < Rails::Application
27
25
  routes.append do
28
- %w'index inputs_block inputs_block_wrapper nest nest_sep nest_inputs nest_seq hash legend combined noblock noblock_post safe_buffer'.each do |action|
26
+ %w'index inputs_block inputs_block_wrapper nest nest_sep nest_inputs nest_seq hash legend combined hidden_tags noblock noblock_post safe_buffer'.each do |action|
29
27
  get action, :controller=>'forme', :action=>action
30
28
  end
31
29
  end
@@ -194,6 +192,10 @@ END
194
192
  END
195
193
  end
196
194
 
195
+ def hidden_tags
196
+ render :inline => "<%= forme([:foo, :bar], {:action=>'/baz'}, :hidden_tags=>[{'a'=>'b'}]) %>"
197
+ end
198
+
197
199
  def noblock
198
200
  render :inline => "<%= forme([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') %>"
199
201
  end
@@ -265,6 +267,10 @@ describe "Forme Rails integration" do
265
267
  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>'
266
268
  end
267
269
 
270
+ silence_warnings "#form should support :hidden_tags option" do
271
+ sin_get('/hidden_tags').must_equal '<form action="/baz"><input name="a" type="hidden" value="b"/></form>'
272
+ end
273
+
268
274
  it "#form should work without a block" do
269
275
  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>'
270
276
  end
@@ -1,8 +1,7 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
- require File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_helper.rb')
3
- require File.join(File.dirname(File.expand_path(__FILE__)), 'erb_helper.rb')
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,42 @@ rescue LoadError
17
16
  rescue LoadError
18
17
  require 'tilt/erb'
19
18
  end
20
- end
21
-
22
- class FormeRodaTest < Roda
23
- opts[:check_dynamic_arity] = opts[:check_arity] = :warn
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
- route do |r|
38
- r.get 'use_request_specific_token', :use do |use|
39
- render :inline=>"[#{Base64.strict_encode64(send(:csrf_secret))}]<%= form({:method=>:post}, {:use_request_specific_token=>#{use == '1'}}) %>"
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
- r.get 'hidden_tags' do |use|
42
- render :inline=>"<%= form({:method=>:post}, {:hidden_tags=>[{:foo=>'bar'}]}) %>"
38
+
39
+ def erb(s, opts={})
40
+ render(opts.merge(:inline=>s))
43
41
  end
44
- r.get 'csrf', :use do |use|
45
- render :inline=>"<%= form({:method=>:post}, {:csrf=>#{use == '1'}}) %>"
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 'hidden_tags2' do |use|
48
+ render :inline=>"<%= form({:method=>:post}, {:hidden_tags=>[{:foo=>'bar'}]}) %>"
49
+ end
50
+ r.get 'csrf', :use do |use|
51
+ render :inline=>"<%= form({:method=>:post}, {:csrf=>#{use == '1'}}) %>"
52
+ end
53
+ instance_exec(r, &block)
46
54
  end
47
- instance_exec(r, &ERB_BLOCK)
48
55
  end
49
56
  end
50
57
 
@@ -54,7 +61,7 @@ rescue LoadError
54
61
  warn "unable to load rack/csrf, skipping roda csrf plugin spec"
55
62
  else
56
63
  describe "Forme Roda ERB integration with roda forme and csrf plugins" do
57
- app = FormeRodaCSRFTest = Class.new(FormeRodaTest)
64
+ app = FormeRodaCSRFTest = FormeRodaTest()
58
65
  app.plugin :csrf
59
66
  app.plugin :forme
60
67
 
@@ -68,64 +75,89 @@ describe "Forme Roda ERB integration with roda forme and csrf plugins" do
68
75
  end
69
76
  end
70
77
 
78
+ module FormeRouteCsrfSpecs
79
+ extend Minitest::Spec::DSL
80
+ include FormeErbSpecs
81
+
82
+ it "should have a valid CSRF tag" do
83
+ output = sin_get('/use_request_specific_token/1')
84
+ output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
85
+ secret = $1
86
+ token = $2
87
+ 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
88
+ 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
89
+ end
90
+
91
+ it "should handle the :use_request_specific_token => true option" do
92
+ output = sin_get('/use_request_specific_token/1')
93
+ output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
94
+ secret = $1
95
+ token = $2
96
+ 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
97
+ 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
98
+ end
99
+
100
+ it "should handle the :use_request_specific_token => false option" do
101
+ output = sin_get('/use_request_specific_token/0')
102
+ output =~ /\[([^\]]+)\].*?value=\"([^\"]+)\"/
103
+ secret = $1
104
+ token = $2
105
+ 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)
106
+ end
107
+
108
+ silence_warnings "should include :hidden_tags option" do
109
+ sin_get('/hidden_tags2').must_include 'name="foo" type="hidden" value="bar"'
110
+ end
111
+
112
+ it "should handle the :csrf option" do
113
+ sin_get('/csrf/1').must_include '<input name="_csrf" type="hidden" value="'
114
+ sin_get('/csrf/0').wont_include '<input name="_csrf" type="hidden" value="'
115
+ end
116
+ end
117
+
71
118
  begin
72
119
  require 'roda/plugins/route_csrf'
120
+ require 'roda/plugins/capture_erb'
121
+ require 'roda/plugins/inject_erb'
73
122
  rescue LoadError
74
- warn "unable to load roda/plugins/route_csrf, skipping forme_route_csrf plugin spec"
123
+ warn "unable to load necessary Roda plugins, skipping forme_erubi_capture plugin spec"
75
124
  else
125
+ describe "Forme Roda Erubi::CaptureEnd integration with roda forme_route_csrf" do
126
+ app = FormeRodaTest(ERUBI_CAPTURE_BLOCK)
127
+ app.plugin :forme_erubi_capture
128
+ app.plugin :render, :engine_opts=>{'erb'=>{:engine_class=>Erubi::CaptureEndEngine}}
129
+
130
+ define_method(:app){app}
131
+ define_method(:plugin_opts){{}}
132
+ define_method(:sin_get) do |path|
133
+ s = String.new
134
+ app.call(@rack.merge('PATH_INFO'=>path))[2].each{|str| s << str}
135
+ s.gsub(/\s+/, ' ').strip
136
+ end
137
+
138
+ include FormeRouteCsrfSpecs
139
+ end if defined?(ERUBI_CAPTURE_BLOCK)
140
+
76
141
  [{}, {:require_request_specific_tokens=>false}].each do |plugin_opts|
77
142
  describe "Forme Roda ERB integration with roda forme_route_csrf and route_csrf plugin with #{plugin_opts}" do
78
- app = Class.new(FormeRodaTest)
143
+ app = FormeRodaTest()
79
144
  app.plugin :forme_route_csrf
80
145
  app.plugin :route_csrf, plugin_opts
81
146
 
147
+ define_method(:app){app}
148
+ define_method(:plugin_opts){plugin_opts}
82
149
  define_method(:sin_get) do |path|
83
150
  s = String.new
84
151
  app.call(@rack.merge('PATH_INFO'=>path))[2].each{|str| s << str}
85
152
  s.gsub(/\s+/, ' ').strip
86
153
  end
87
154
 
88
- include FormeErbSpecs
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
155
+ include FormeRouteCsrfSpecs
124
156
  end
125
157
 
126
158
  describe "Forme Roda ERB Sequel integration with roda forme_set plugin and route_csrf plugin with #{plugin_opts}" do
127
159
  before do
128
- @app = Class.new(FormeRodaTest)
160
+ @app = FormeRodaTest()
129
161
  @app.plugin :route_csrf, plugin_opts
130
162
  @app.plugin(:forme_set, :secret=>'1'*64)
131
163
 
@@ -153,7 +185,11 @@ else
153
185
 
154
186
  @app.route do |r|
155
187
  r.get do
156
- form(*env[:args], &env[:block]).to_s
188
+ if @block = env[:block]
189
+ render(:inline=>'<% form(*env[:args]) do |f| %><%= @block.call(f) %><% end %>')
190
+ else
191
+ form(*env[:args])
192
+ end
157
193
  end
158
194
  r.post do
159
195
  r.params.replace(env[:params])
@@ -173,6 +209,25 @@ else
173
209
  end
174
210
  meth == :forme_parse ? ret : h
175
211
  end
212
+
213
+ it "should have subform work correctly" do
214
+ @app.route do |r|
215
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
216
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
217
+ erb <<END
218
+ 0
219
+ <% form(@album, {:action=>'/baz'}, :button=>'Sub') do |f| %>
220
+ 1
221
+ <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo', :grid=>true, :labels=>%w'Name') %>
222
+ 2
223
+ <% end %>
224
+ 3
225
+ END
226
+ end
227
+
228
+ body = @app.call('REQUEST_METHOD'=>'GET')[2].join.gsub("\n", ' ').gsub(/ +/, ' ').chomp(' ')
229
+ 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 <table><caption>Foo</caption><thead><tr><th>Name</th></tr></thead><tbody><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="2"/><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'
230
+ end
176
231
 
177
232
  it "#forme_set should include HMAC values if form includes inputs for obj" do
178
233
  h = forme_set(@ab, :name=>'Foo')
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'sequel'
3
2
 
4
3
  db_url = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' ? 'jdbc:sqlite::memory:' : 'sqlite:/'
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_helper.rb')
1
+ require_relative 'sequel_helper'
2
2
 
3
3
  gem 'i18n', '>= 0.7.0'
4
4
  require 'i18n'
@@ -1,8 +1,8 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
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 File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_i18n_helper.rb')
5
+ require_relative 'sequel_i18n_helper'
6
6
  rescue LoadError
7
7
  warn "unable to load i18n, skipping i18n Sequel plugin spec"
8
8
  else