forme 1.9.0 → 2.0.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +70 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +396 -202
  5. data/lib/forme/bs3.rb +19 -5
  6. data/lib/forme/erb.rb +18 -16
  7. data/lib/forme/form.rb +151 -118
  8. data/lib/forme/input.rb +1 -1
  9. data/lib/forme/rails.rb +41 -72
  10. data/lib/forme/raw.rb +2 -2
  11. data/lib/forme/sinatra.rb +6 -2
  12. data/lib/forme/tag.rb +3 -12
  13. data/lib/forme/template.rb +118 -0
  14. data/lib/forme/transformers/error_handler.rb +46 -1
  15. data/lib/forme/transformers/formatter.rb +36 -35
  16. data/lib/forme/transformers/helper.rb +0 -1
  17. data/lib/forme/transformers/inputs_wrapper.rb +6 -6
  18. data/lib/forme/transformers/labeler.rb +19 -0
  19. data/lib/forme/transformers/wrapper.rb +1 -1
  20. data/lib/forme/version.rb +2 -2
  21. data/lib/forme.rb +15 -2
  22. data/lib/roda/plugins/forme.rb +1 -1
  23. data/lib/roda/plugins/forme_erubi_capture.rb +62 -0
  24. data/lib/roda/plugins/forme_route_csrf.rb +16 -20
  25. data/lib/roda/plugins/forme_set.rb +177 -0
  26. data/lib/sequel/plugins/forme.rb +42 -55
  27. data/lib/sequel/plugins/forme_i18n.rb +3 -1
  28. data/lib/sequel/plugins/forme_set.rb +50 -28
  29. data/spec/all.rb +1 -1
  30. data/spec/bs3_reference_spec.rb +18 -18
  31. data/spec/bs3_sequel_plugin_spec.rb +7 -7
  32. data/spec/bs3_spec.rb +23 -11
  33. data/spec/erb_helper.rb +73 -58
  34. data/spec/erubi_capture_helper.rb +202 -0
  35. data/spec/forme_spec.rb +80 -29
  36. data/spec/rails_integration_spec.rb +47 -24
  37. data/spec/roda_integration_spec.rb +459 -48
  38. data/spec/sequel_helper.rb +0 -1
  39. data/spec/sequel_i18n_helper.rb +1 -1
  40. data/spec/sequel_i18n_plugin_spec.rb +3 -2
  41. data/spec/sequel_plugin_spec.rb +25 -8
  42. data/spec/sequel_set_plugin_spec.rb +10 -3
  43. data/spec/shared_erb_specs.rb +75 -0
  44. data/spec/sinatra_integration_spec.rb +5 -6
  45. data/spec/spec_helper.rb +23 -5
  46. metadata +30 -8
  47. data/lib/forme/erb_form.rb +0 -74
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)
@@ -116,13 +116,13 @@ describe "Forme plain forms" do
116
116
 
117
117
  it "should consider form's :errors hash based on the :key option" do
118
118
  @f.opts[:errors] = { 'foo' => 'must be present' }
119
- @f.input(:text, :key=>"foo").to_s.must_equal "<input class=\"error\" id=\"foo\" name=\"foo\" type=\"text\"/><span class=\"error_message\">must be present</span>"
119
+ @f.input(:text, :key=>"foo").to_s.must_equal "<input aria-describedby=\"foo_error_message\" aria-invalid=\"true\" class=\"error\" id=\"foo\" name=\"foo\" type=\"text\"/><span class=\"error_message\" id=\"foo_error_message\">must be present</span>"
120
120
  end
121
121
 
122
122
  it "should consider form's :errors hash based on the :key option when using namespaces" do
123
123
  @f.opts[:errors] = { 'bar' => { 'foo' => 'must be present' } }
124
124
  @f.with_opts(:namespace=>['bar']) do
125
- @f.input(:text, :key=>"foo").to_s.must_equal "<input class=\"error\" id=\"bar_foo\" name=\"bar[foo]\" type=\"text\"/><span class=\"error_message\">must be present</span>"
125
+ @f.input(:text, :key=>"foo").to_s.must_equal "<input aria-describedby=\"bar_foo_error_message\" aria-invalid=\"true\" class=\"error\" id=\"bar_foo\" name=\"bar[foo]\" type=\"text\"/><span class=\"error_message\" id=\"bar_foo_error_message\">must be present</span>"
126
126
  end
127
127
  end
128
128
 
@@ -301,6 +301,10 @@ describe "Forme plain forms" do
301
301
  @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5)).to_s.must_equal %{<select id="bar" name="foo[year]">#{sel(1900..2050, 2011)}</select>-<select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>}
302
302
  end
303
303
 
304
+ it "should use labels for select boxes for dates if the :as=>:select and :select_labels options are given" do
305
+ @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :select_labels=>{:year=>'Y', :month=>'M', :day=>'D'}, :labeler=>:explicit).to_s.must_equal %{<label class="label-before" for="bar">Y</label><select id="bar" name="foo[year]">#{sel(1900..2050, 2011)}</select>-<label class="label-before" for="bar_month">M</label><select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<label class="label-before" for="bar_day">D</label><select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>}
306
+ end
307
+
304
308
  it "should allow ordering date select boxes via :order" do
305
309
  @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :order=>[:month, '/', :day, '/', :year]).to_s.must_equal %{<select id="bar" name="foo[month]">#{sel(1..12, 6)}</select>/<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>/<select id="bar_year" name="foo[year]">#{sel(1900..2050, 2011)}</select>}
306
310
  end
@@ -313,6 +317,10 @@ describe "Forme plain forms" do
313
317
  @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :select_options=>{:year=>1970..2020}).to_s.must_equal %{<select id="bar" name="foo[year]">#{sel(1970..2020, 2011)}</select>-<select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>}
314
318
  end
315
319
 
320
+ it "should support :select_options with both values and text for dates when :as=>:select is given" do
321
+ @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :select_options=>{:year=>[[2011, 'A'], [2012, 'B']]}).to_s.must_equal %{<select id="bar" name="foo[year]"><option selected="selected" value="2011">A</option><option value="2012">B</option></select>-<select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>}
322
+ end
323
+
316
324
  it "should have explicit labeler and trtd wrapper work with multiple select boxes for dates" do
317
325
  @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :wrapper=>:trtd, :labeler=>:explicit, :label=>'Baz').to_s.must_equal %{<tr><td><label class="label-before" for="bar">Baz</label></td><td><select id="bar" name="foo[year]">#{sel(1900..2050, 2011)}</select>-<select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select></td></tr>}
318
326
  end
@@ -433,7 +441,11 @@ describe "Forme plain forms" do
433
441
  end
434
442
 
435
443
  it "should create set of radio buttons with :error and :error_attr options" do
436
- @f.input(:radioset, :options=>[1, 2, 3], :selected=>2, :error=>'foo', :error_attr=>{'bar'=>'baz'}).to_s.must_equal '<label class="option"><input type="radio" value="1"/> 1</label><label class="option"><input checked="checked" type="radio" value="2"/> 2</label><label class="option"><input class="error" type="radio" value="3"/> 3</label><span bar="baz" class="error_message">foo</span>'
444
+ @f.input(:radioset, :options=>[1, 2, 3], :selected=>2, :error=>'foo', :error_attr=>{'bar'=>'baz'}).to_s.must_equal '<label class="option"><input type="radio" value="1"/> 1</label><label class="option"><input checked="checked" type="radio" value="2"/> 2</label><label class="option"><input aria-invalid="true" class="error" type="radio" value="3"/> 3</label><span bar="baz" class="error_message">foo</span>'
445
+ end
446
+
447
+ it "should support custom error_handler for set of radio buttons" do
448
+ @f.input(:radioset, :options=>[1, 2, 3], :selected=>2, :error=>'foo', :error_attr=>{'bar'=>'baz'}, :error_handler=>lambda{|tag, input| input.tag(:div, {}, tag)}).to_s.must_equal '<div><label class="option"><input type="radio" value="1"/> 1</label><label class="option"><input checked="checked" type="radio" value="2"/> 2</label><label class="option"><input type="radio" value="3"/> 3</label></div>'
437
449
  end
438
450
 
439
451
  it "should create set of checkbox buttons" do
@@ -457,10 +469,26 @@ describe "Forme plain forms" do
457
469
  @f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :label=>'foo').to_s.must_equal '<span class="label">foo</span><label class="option"><input type="checkbox" value="1"/> a</label><label class="option"><input type="checkbox" value="2"/> b</label><label class="option"><input type="checkbox" value="3"/> c</label>'
458
470
  end
459
471
 
472
+ it "should support fieldset/legend for checkboxsets" do
473
+ @f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :label=>'foo', :labeler=>:legend, :wrapper=>:fieldset).to_s.must_equal '<fieldset><legend>foo</legend><label class="option"><input type="checkbox" value="1"/> a</label><label class="option"><input type="checkbox" value="2"/> b</label><label class="option"><input type="checkbox" value="3"/> c</label></fieldset>'
474
+ end
475
+
476
+ it "should support legend with attributes for checkboxsets" do
477
+ @f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :label=>'foo', :label_attr=>{:class=>"baz"}, :tag_label_attr=>{:class=>"bar"}, :labeler=>:legend, :wrapper=>:fieldset).to_s.must_equal '<fieldset><legend class="baz">foo</legend><label class="bar"><input type="checkbox" value="1"/> a</label><label class="bar"><input type="checkbox" value="2"/> b</label><label class="bar"><input type="checkbox" value="3"/> c</label></fieldset>'
478
+ end
479
+
480
+ it "should support legend with attributes for checkboxsets, handling errors with :error_handler=>:after_legend" do
481
+ @f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :id=>:quux, :label=>'foo', :label_attr=>{:class=>"baz"}, :tag_label_attr=>{:class=>"bar"}, :labeler=>:legend, :wrapper=>:fieldset, :error=>'bar2', :error_handler=>:after_legend).to_s.must_equal '<fieldset><legend class="baz">foo</legend><span class="error_message" id="quux_1_error_message">bar2</span><label class="bar"><input aria-describedby="quux_1_error_message" aria-invalid="true" class="error" id="quux_1" type="checkbox" value="1"/> a</label><label class="bar"><input id="quux_2" type="checkbox" value="2"/> b</label><label class="bar"><input id="quux_3" type="checkbox" value="3"/> c</label></fieldset>'
482
+ end
483
+
460
484
  it "should support :tag_labeler for checkboxsets" do
461
485
  @f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :tag_labeler=>:explicit).to_s.must_equal '<input type="checkbox" value="1"/><label class="option label-after">a</label><input type="checkbox" value="2"/><label class="option label-after">b</label><input type="checkbox" value="3"/><label class="option label-after">c</label>'
462
486
  end
463
487
 
488
+ it "should support custom :labeler for checkboxsets" do
489
+ @f.input(:checkboxset, :options=>[[:a, 1], [:b, 2], [:c, 3]], :label=>'foo', :labeler=>lambda{|tag, input| input.tag(:div, {}, tag)}).to_s.must_equal '<div><label class="option"><input type="checkbox" value="1"/> a</label><label class="option"><input type="checkbox" value="2"/> b</label><label class="option"><input type="checkbox" value="3"/> c</label></div>'
490
+ end
491
+
464
492
  it "should create set of checkbox buttons with options and values with hashes" do
465
493
  @f.input(:checkboxset, :options=>[[:a, {:attr=>{:foo=>1}}], [:b, {:class=>'foo', :value=>2}], [:c, {:id=>:baz}]], :selected=>2).to_s.must_equal '<label class="option"><input foo="1" type="checkbox" value="a"/> a</label><label class="option"><input checked="checked" class="foo" type="checkbox" value="2"/> b</label><label class="option"><input id="baz" type="checkbox" value="c"/> c</label>'
466
494
  end
@@ -491,7 +519,7 @@ describe "Forme plain forms" do
491
519
  end
492
520
 
493
521
  it "should respect the :error option for checkbox sets" do
494
- @f.input(:checkboxset, :options=>[1, 2, 3], :error=>'foo', :value=>2).to_s.must_equal '<label class="option"><input type="checkbox" value="1"/> 1</label><label class="option"><input checked="checked" type="checkbox" value="2"/> 2</label><label class="option"><input class="error" type="checkbox" value="3"/> 3</label><span class="error_message">foo</span>'
522
+ @f.input(:checkboxset, :options=>[1, 2, 3], :error=>'foo', :value=>2).to_s.must_equal '<label class="option"><input type="checkbox" value="1"/> 1</label><label class="option"><input checked="checked" type="checkbox" value="2"/> 2</label><label class="option"><input aria-invalid="true" class="error" type="checkbox" value="3"/> 3</label><span class="error_message">foo</span>'
495
523
  end
496
524
 
497
525
  it "should create set of checkbox buttons with fieldsets and legends for optgroups" do
@@ -558,19 +586,23 @@ describe "Forme plain forms" do
558
586
  end
559
587
 
560
588
  it "should automatically note the input has errors if :error option is used" do
561
- @f.input(:text, :error=>'Bad Stuff!', :value=>'foo').to_s.must_equal '<input class="error" type="text" value="foo"/><span class="error_message">Bad Stuff!</span>'
589
+ @f.input(:text, :error=>'Bad Stuff!', :value=>'foo').to_s.must_equal '<input aria-invalid="true" class="error" type="text" value="foo"/><span class="error_message">Bad Stuff!</span>'
562
590
  end
563
591
 
564
592
  it "should add an error message after the label" do
565
- @f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :label=>"Foo").to_s.must_equal '<label>Foo: <input class="error" type="text" value="foo"/></label><span class="error_message">Bad Stuff!</span>'
593
+ @f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :label=>"Foo").to_s.must_equal '<label>Foo: <input aria-invalid="true" class="error" type="text" value="foo"/></label><span class="error_message">Bad Stuff!</span>'
566
594
  end
567
595
 
568
596
  it "should add to existing :class option if :error option is used" do
569
- @f.input(:text, :error=>'Bad Stuff!', :class=>'bar', :value=>'foo').to_s.must_equal '<input class="bar error" type="text" value="foo"/><span class="error_message">Bad Stuff!</span>'
597
+ @f.input(:text, :error=>'Bad Stuff!', :class=>'bar', :value=>'foo').to_s.must_equal '<input aria-invalid="true" class="bar error" type="text" value="foo"/><span class="error_message">Bad Stuff!</span>'
570
598
  end
571
599
 
572
600
  it "should respect :error_attr option for setting the attributes for the error message span" do
573
- @f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :error_attr=>{:class=>'foo'}).to_s.must_equal '<input class="error" type="text" value="foo"/><span class="foo error_message">Bad Stuff!</span>'
601
+ @f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :error_attr=>{:class=>'foo'}).to_s.must_equal '<input aria-invalid="true" class="error" type="text" value="foo"/><span class="foo error_message">Bad Stuff!</span>'
602
+ end
603
+
604
+ it "should use aria-describedby and aria-invalid tags for errors with where the id attribute can be determined" do
605
+ @f.input(:text, :error=>'Bad Stuff!', :id=>:bar, :value=>'foo', :error_attr=>{:class=>'foo'}).to_s.must_equal '<input aria-describedby="bar_error_message" aria-invalid="true" class="error" id="bar" type="text" value="foo"/><span class="foo error_message" id="bar_error_message">Bad Stuff!</span>'
574
606
  end
575
607
 
576
608
  it "#open should return an opening tag" do
@@ -599,13 +631,19 @@ describe "Forme plain forms" do
599
631
  @f.tag(:textarea, {:name=>:foo}, :bar).to_s.must_equal '<textarea name="foo">bar</textarea>'
600
632
  end
601
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
+
602
640
  it "#tag should accept children as procs" do
603
- @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>'
604
642
  end
605
643
 
606
644
  it "#tag should accept children as methods" do
607
645
  o = Object.new
608
- 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
609
647
  @f.tag(:div, {:class=>"foo"}, o.method(:foo)).to_s.must_equal '<div class="foo"><input class="foo"/></div>'
610
648
  end
611
649
 
@@ -613,6 +651,10 @@ describe "Forme plain forms" do
613
651
  @f.inputs([:textarea, :text]).to_s.must_equal '<fieldset class="inputs"><textarea></textarea><input type="text"/></fieldset>'
614
652
  end
615
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
+
616
658
  it "should have default #inputs method accept an :attr option" do
617
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>'
618
660
  end
@@ -696,7 +738,7 @@ describe "Forme plain forms" do
696
738
  end
697
739
 
698
740
  it "inputs should have helper displayed inside wrapper, after error" do
699
- @f.input(:text, :help=>"List type of foo", :error=>'bad', :wrapper=>:li).to_s.must_equal '<li><input class="error" type="text"/><span class="error_message">bad</span><span class="helper">List type of foo</span></li>'
741
+ @f.input(:text, :help=>"List type of foo", :error=>'bad', :wrapper=>:li).to_s.must_equal '<li><input aria-invalid="true" class="error" type="text"/><span class="error_message">bad</span><span class="helper">List type of foo</span></li>'
700
742
  end
701
743
 
702
744
  it "inputs should accept a :formatter option to use a custom formatter" do
@@ -729,7 +771,7 @@ describe "Forme plain forms" do
729
771
  end
730
772
 
731
773
  it "inputs should accept a :error_handler option to use a custom error_handler" do
732
- @f.input(:textarea, :error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}, :error=>'bar', :id=>:foo).to_s.must_equal '<textarea class="error" id="foo"></textarea>!!! bar'
774
+ @f.input(:textarea, :error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}, :error=>'bar', :id=>:foo).to_s.must_equal '<textarea aria-describedby="foo_error_message" aria-invalid="true" class="error" id="foo"></textarea>!!! bar'
733
775
  end
734
776
 
735
777
  it "#inputs should accept a :inputs_wrapper option to use a custom inputs_wrapper" do
@@ -745,7 +787,7 @@ describe "Forme plain forms" do
745
787
  end
746
788
 
747
789
  it "inputs should accept a :error_handler=>nil option to not use an error_handler" do
748
- @f.input(:textarea, :error_handler=>nil, :error=>'bar', :id=>:foo).to_s.must_equal '<textarea class="error" id="foo"></textarea>'
790
+ @f.input(:textarea, :error_handler=>nil, :error=>'bar', :id=>:foo).to_s.must_equal '<textarea aria-invalid="true" class="error" id="foo"></textarea>'
749
791
  end
750
792
 
751
793
  it "#inputs should accept a :inputs_wrapper=>nil option to not use an inputs_wrapper" do
@@ -773,41 +815,45 @@ describe "Forme plain forms" do
773
815
  proc{@f.input(:textarea, :wrapper=>Object.new).to_s}.must_raise(Forme::Error)
774
816
  proc{@f.input(:textarea, :formatter=>nil).to_s}.must_raise(Forme::Error)
775
817
  end
776
- end
777
818
 
778
- describe "Forme::Form :hidden_tags option " do
779
- before do
780
- @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>'
781
821
  end
822
+ end
782
823
 
783
- it "should handle hash" do
824
+ describe "Forme::Form :hidden_tags option " do
825
+ silence_warnings "should handle hash" do
784
826
  Forme.form({}, :hidden_tags=>[{:a=>'b'}]).to_s.must_equal '<form><input name="a" type="hidden" value="b"/></form>'
785
827
  end
786
828
 
787
- it "should handle array" do
829
+ silence_warnings "should handle array" do
788
830
  Forme.form({}, :hidden_tags=>[["a ", "b"]]).to_s.must_equal '<form>a b</form>'
789
831
  end
790
832
 
791
- it "should handle string" do
833
+ silence_warnings "should handle string" do
792
834
  Forme.form({}, :hidden_tags=>["a "]).to_s.must_equal '<form>a </form>'
793
835
  end
794
836
 
795
- it "should handle proc return hash" do
837
+ silence_warnings "should handle proc return hash" do
796
838
  Forme.form({}, :hidden_tags=>[lambda{|tag| {:a=>'b'}}]).to_s.must_equal '<form><input name="a" type="hidden" value="b"/></form>'
797
839
  end
798
840
 
799
- it "should handle proc return tag" do
800
- 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>'
801
843
  end
802
844
 
803
- it "should raise error for unhandled object" do
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>'
847
+ end
848
+
849
+ silence_warnings "should raise error for unhandled object" do
804
850
  proc{Forme.form({}, :hidden_tags=>[Object.new])}.must_raise Forme::Error
805
851
  end
806
852
  end
807
853
 
808
854
  describe "Forme custom" do
809
855
  it "formatters can be specified as a proc" do
810
- 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>'
811
857
  end
812
858
 
813
859
  it "serializers can be specified as a proc" do
@@ -819,7 +865,7 @@ describe "Forme custom" do
819
865
  end
820
866
 
821
867
  it "error_handlers can be specified as a proc" do
822
- Forme::Form.new(:error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}).input(:textarea, :name=>'foo', :error=>'bar').to_s.must_equal '<textarea class="error" name="foo"></textarea>!!! bar'
868
+ Forme::Form.new(:error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}).input(:textarea, :name=>'foo', :error=>'bar').to_s.must_equal '<textarea aria-invalid="true" class="error" name="foo"></textarea>!!! bar'
823
869
  end
824
870
 
825
871
  it "wrappers can be specified as a proc" do
@@ -854,6 +900,10 @@ describe "Forme built-in custom" do
854
900
  Forme::Form.new(:formatter=>:readonly).input(:select, :label=>"Foo", :options=>[1, 2, 3], :value=>2).to_s.must_equal "<label>Foo: <span>2</span></label>"
855
901
  end
856
902
 
903
+ it "formatter: readonly removes hidden inputs" do
904
+ Forme::Form.new(:formatter=>:readonly).input(:hidden, :value=>"Bar").to_s.must_equal ""
905
+ end
906
+
857
907
  it "formatter: readonly formats text into paragraphs for textarea inputs" do
858
908
  Forme::Form.new(:formatter=>:readonly).input(:textarea, :label=>"Foo", :value=>"\n Bar\nBaz\n\nQuuz\n\n1\n2 \n").to_s.must_equal "<label>Foo: <div class=\"readonly-textarea\"><p> Bar<br />Baz</p><p>Quuz</p><p>1<br />2 </p></div></label>"
859
909
  end
@@ -877,7 +927,7 @@ describe "Forme built-in custom" do
877
927
  end
878
928
 
879
929
  it "labeler: explicit should handle tags with errors" do
880
- Forme::Form.new(:labeler=>:explicit).input(:text, :error=>'Bad Stuff!', :value=>'f', :id=>'foo', :label=>'bar').to_s.must_equal '<label class="label-before" for="foo">bar</label><input class="error" id="foo" type="text" value="f"/><span class="error_message">Bad Stuff!</span>'
930
+ Forme::Form.new(:labeler=>:explicit).input(:text, :error=>'Bad Stuff!', :value=>'f', :id=>'foo', :label=>'bar').to_s.must_equal '<label class="label-before" for="foo">bar</label><input aria-describedby="foo_error_message" aria-invalid="true" class="error" id="foo" type="text" value="f"/><span class="error_message" id="foo_error_message">Bad Stuff!</span>'
881
931
  end
882
932
 
883
933
  it "wrapper: li wraps tag in an li" do
@@ -915,7 +965,7 @@ describe "Forme built-in custom" do
915
965
  end
916
966
 
917
967
  it "wrapper: trtd should use at most 2 td tags" do
918
- Forme::Form.new(:wrapper=>:trtd, :labeler=>:explicit).input(:textarea, :id=>'foo', :label=>'Foo', :error=>'Bar').to_s.must_equal '<tr><td><label class="label-before" for="foo">Foo</label></td><td><textarea class="error" id="foo"></textarea><span class="error_message">Bar</span></td></tr>'
968
+ Forme::Form.new(:wrapper=>:trtd, :labeler=>:explicit).input(:textarea, :id=>'foo', :label=>'Foo', :error=>'Bar').to_s.must_equal '<tr><td><label class="label-before" for="foo">Foo</label></td><td><textarea aria-describedby="foo_error_message" aria-invalid="true" class="error" id="foo"></textarea><span class="error_message" id="foo_error_message">Bar</span></td></tr>'
919
969
  end
920
970
 
921
971
  it "wrapper: trtd should handle inputs with label after" do
@@ -1020,6 +1070,7 @@ describe "Forme built-in custom" do
1020
1070
  Forme::Form.new(:serializer=>:text).button().to_s.must_equal ""
1021
1071
  Forme::Form.new(:serializer=>:text).inputs([[:textarea, {:label=>"Foo", :value=>"Bar"}]], :legend=>'Baz').to_s.must_equal "Baz\n---\nFoo: Bar\n\n"
1022
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"
1023
1074
  end
1024
1075
  end
1025
1076
 
@@ -1,33 +1,48 @@
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
- require 'action_controller/railtie'
7
- rescue LoadError
8
- warn "unable to load rails, skipping rails spec"
9
- else
10
- begin
11
- require 'active_pack/gem_version'
12
- rescue LoadError
13
- end
14
- require 'forme/rails'
5
+ require 'action_controller/railtie'
15
6
 
16
- class FormeRails < Rails::Application
17
- routes.append do
18
- %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|
19
- get action, :controller=>'forme', :action=>action
7
+ begin
8
+ require 'active_pack/gem_version'
9
+ rescue LoadError
10
+ end
11
+ require_relative '../lib/forme/rails'
12
+
13
+ if Rails.respond_to?(:version) && Rails.version.start_with?('4')
14
+ # Work around issue in backported openssl environments where
15
+ # secret is 64 bytes intead of 32 bytes
16
+ require 'active_support/message_encryptor'
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
20
21
  end
21
22
  end
22
- config.active_support.deprecation = :stderr
23
- config.middleware.delete(ActionDispatch::ShowExceptions)
24
- config.middleware.delete(Rack::Lock)
25
- config.secret_key_base = 'foo'*15
26
- config.secret_token = 'secret token'*15 if Rails.respond_to?(:version) && Rails.version < '5.2'
27
- config.eager_load = true
28
- initialize!
29
- end
30
23
 
24
+ class FormeRails < Rails::Application
25
+ routes.append do
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|
27
+ get action, :controller=>'forme', :action=>action
28
+ end
29
+ end
30
+ config.active_support.deprecation = :stderr
31
+ config.middleware.delete(ActionDispatch::HostAuthorization) if defined?(ActionDispatch::HostAuthorization)
32
+ config.middleware.delete(ActionDispatch::ShowExceptions)
33
+ config.middleware.delete(Rack::Lock)
34
+ config.secret_key_base = 'foo'*15
35
+ config.secret_token = 'secret token'*15 if Rails.respond_to?(:version) && Rails.version < '5.2'
36
+ config.eager_load = true
37
+ begin
38
+ initialize!
39
+ rescue NoMethodError
40
+ raise LoadError
41
+ end
42
+ end
43
+ rescue LoadError
44
+ warn "unable to load or setup rails, skipping rails spec"
45
+ else
31
46
  class FormeController < ActionController::Base
32
47
  helper Forme::Rails::ERB
33
48
 
@@ -177,6 +192,10 @@ END
177
192
  END
178
193
  end
179
194
 
195
+ def hidden_tags
196
+ render :inline => "<%= forme([:foo, :bar], {:action=>'/baz'}, :hidden_tags=>[{'a'=>'b'}]) %>"
197
+ end
198
+
180
199
  def noblock
181
200
  render :inline => "<%= forme([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') %>"
182
201
  end
@@ -248,6 +267,10 @@ describe "Forme Rails integration" do
248
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>'
249
268
  end
250
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
+
251
274
  it "#form should work without a block" do
252
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>'
253
276
  end