formtastic 2.1.1 → 2.2.0.rc

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 (54) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +19 -1
  3. data/Appraisals +7 -0
  4. data/CHANGELOG +18 -0
  5. data/README.textile +14 -16
  6. data/formtastic.gemspec +1 -1
  7. data/gemfiles/rails-4.gemfile +8 -0
  8. data/lib/formtastic/form_builder.rb +0 -1
  9. data/lib/formtastic/helpers/input_helper.rb +12 -26
  10. data/lib/formtastic/inputs.rb +6 -0
  11. data/lib/formtastic/inputs/base.rb +16 -4
  12. data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
  13. data/lib/formtastic/inputs/base/stringish.rb +10 -2
  14. data/lib/formtastic/inputs/base/timeish.rb +17 -17
  15. data/lib/formtastic/inputs/base/wrapping.rb +25 -20
  16. data/lib/formtastic/inputs/boolean_input.rb +24 -1
  17. data/lib/formtastic/inputs/date_input.rb +5 -29
  18. data/lib/formtastic/inputs/date_picker_input.rb +93 -0
  19. data/lib/formtastic/inputs/date_select_input.rb +34 -0
  20. data/lib/formtastic/inputs/datetime_input.rb +6 -8
  21. data/lib/formtastic/inputs/datetime_picker_input.rb +100 -0
  22. data/lib/formtastic/inputs/datetime_select_input.rb +12 -0
  23. data/lib/formtastic/inputs/hidden_input.rb +1 -1
  24. data/lib/formtastic/inputs/radio_input.rb +1 -1
  25. data/lib/formtastic/inputs/select_input.rb +2 -5
  26. data/lib/formtastic/inputs/time_input.rb +4 -28
  27. data/lib/formtastic/inputs/time_picker_input.rb +99 -0
  28. data/lib/formtastic/inputs/time_select_input.rb +34 -0
  29. data/lib/formtastic/version.rb +1 -1
  30. data/lib/generators/templates/formtastic.rb +0 -8
  31. data/sample/basic_inputs.html +21 -1
  32. data/spec/builder/semantic_fields_for_spec.rb +1 -1
  33. data/spec/generators/formtastic/install/install_generator_spec.rb +1 -1
  34. data/spec/helpers/input_helper_spec.rb +20 -16
  35. data/spec/helpers/semantic_errors_helper_spec.rb +10 -10
  36. data/spec/inputs/custom_input_spec.rb +5 -2
  37. data/spec/inputs/date_picker_input_spec.rb +449 -0
  38. data/spec/inputs/{date_input_spec.rb → date_select_input_spec.rb} +34 -34
  39. data/spec/inputs/datetime_picker_input_spec.rb +490 -0
  40. data/spec/inputs/{datetime_input_spec.rb → datetime_select_input_spec.rb} +33 -33
  41. data/spec/inputs/deprecated_time_date_datetime_inputs_spec.rb +48 -0
  42. data/spec/inputs/hidden_input_spec.rb +21 -17
  43. data/spec/inputs/include_blank_spec.rb +3 -3
  44. data/spec/inputs/label_spec.rb +1 -1
  45. data/spec/inputs/placeholder_spec.rb +1 -1
  46. data/spec/inputs/select_input_spec.rb +22 -14
  47. data/spec/inputs/time_picker_input_spec.rb +455 -0
  48. data/spec/inputs/{time_input_spec.rb → time_select_input_spec.rb} +35 -35
  49. data/spec/spec_helper.rb +25 -1
  50. data/spec/support/custom_macros.rb +2 -2
  51. metadata +32 -21
  52. data/lib/formtastic/helpers/buttons_helper.rb +0 -310
  53. data/spec/helpers/buttons_helper_spec.rb +0 -166
  54. data/spec/helpers/commit_button_helper_spec.rb +0 -530
@@ -0,0 +1,99 @@
1
+ module Formtastic
2
+ module Inputs
3
+
4
+ # Outputs a simple `<label>` with a HTML5 `<input type="time">` wrapped in the standard
5
+ # `<li>` wrapper. This is an alternative to `:time_select` for `:date`, `:time`, `:datetime`
6
+ # database columns. You can use this input with `:as => :time_picker`.
7
+ #
8
+ # *Please note:* Formtastic only provides suitable markup for a date picker, but does not supply
9
+ # any additional CSS or Javascript to render calendar-style date pickers. Browsers that support
10
+ # this input type (such as Mobile Webkit and Opera on the desktop) will render a native widget.
11
+ # Browsers that don't will default to a plain text field`<input type="text">` and can be
12
+ # poly-filled with some Javascript and a UI library of your choice.
13
+ #
14
+ # @example Full form context and output
15
+ #
16
+ # <%= semantic_form_for(@post) do |f| %>
17
+ # <%= f.inputs do %>
18
+ # <%= f.input :publish_at, :as => :time_picker %>
19
+ # <% end %>
20
+ # <% end %>
21
+ #
22
+ # <form...>
23
+ # <fieldset>
24
+ # <ol>
25
+ # <li class="string">
26
+ # <label for="post_publish_at">First name</label>
27
+ # <input type="date" id="post_publish_at" name="post[publish_at]">
28
+ # </li>
29
+ # </ol>
30
+ # </fieldset>
31
+ # </form>
32
+ #
33
+ # @example Setting the size (defaults to 5 for HH:MM)
34
+ # <%= f.input :publish_at, :as => :time_picker, :size => 20 %>
35
+ # <%= f.input :publish_at, :as => :time_picker, :input_html => { :size => 20 } %>
36
+ #
37
+ # @example Setting the maxlength (defaults to 5 for HH:MM)
38
+ # <%= f.input :publish_at, :as => :time_picker, :maxlength => 20 %>
39
+ # <%= f.input :publish_at, :as => :time_picker, :input_html => { :maxlength => 20 } %>
40
+ #
41
+ # @example Setting the value (defaults to HH:MM for Date and Time objects, otherwise renders string)
42
+ # <%= f.input :publish_at, :as => :time_picker, :input_html => { :value => "14:14" } %>
43
+ #
44
+ # @example Setting the step attribute (defaults to 60)
45
+ # <%= f.input :publish_at, :as => :time_picker, :step => 120 %>
46
+ # <%= f.input :publish_at, :as => :time_picker, :input_html => { :step => 120 } %>
47
+ #
48
+ # @example Setting the step attribute with a macro
49
+ # <%= f.input :publish_at, :as => :time_picker, :step => :second %>
50
+ # <%= f.input :publish_at, :as => :time_picker, :step => :minute %>
51
+ # <%= f.input :publish_at, :as => :time_picker, :step => :quarter_hour %>
52
+ # <%= f.input :publish_at, :as => :time_picker, :step => :fifteen_minutes %>
53
+ # <%= f.input :publish_at, :as => :time_picker, :step => :half_hour %>
54
+ # <%= f.input :publish_at, :as => :time_picker, :step => :thirty_minutes %>
55
+ # <%= f.input :publish_at, :as => :time_picker, :step => :hour %>
56
+ # <%= f.input :publish_at, :as => :time_picker, :step => :sixty_minutes %>
57
+ #
58
+ # @example Setting the min attribute
59
+ # <%= f.input :publish_at, :as => :time_picker, :min => "09:00" %>
60
+ # <%= f.input :publish_at, :as => :time_picker, :input_html => { :min => "01:00" } %>
61
+ #
62
+ # @example Setting the max attribute
63
+ # <%= f.input :publish_at, :as => :time_picker, :max => "18:00" %>
64
+ # <%= f.input :publish_at, :as => :time_picker, :input_html => { :max => "18:00" } %>
65
+ #
66
+ # @example Setting the placeholder attribute
67
+ # <%= f.input :publish_at, :as => :time_picker, :placeholder => "HH:MM" %>
68
+ # <%= f.input :publish_at, :as => :time_picker, :input_html => { :placeholder => "HH:MM" } %>
69
+ #
70
+ # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
71
+ class TimePickerInput
72
+ include Base
73
+ include Base::Stringish
74
+ include Base::DatetimePickerish
75
+
76
+ def html_input_type
77
+ "time"
78
+ end
79
+
80
+ def default_size
81
+ 5
82
+ end
83
+
84
+ def value
85
+ return options[:input_html][:value] if options[:input_html] && options[:input_html].key?(:value)
86
+ val = object.send(method)
87
+ return "00:00" if val.is_a?(Date)
88
+ return val.strftime("%H:%M") if val.is_a?(Time)
89
+ return val if val.nil?
90
+ val.to_s
91
+ end
92
+
93
+ def default_step
94
+ 60
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,34 @@
1
+ module Formtastic
2
+ module Inputs
3
+ # Outputs a series of select boxes for the fragments that make up a time (hour, minute, second).
4
+ # Unless `:ignore_date` is true, it will render hidden inputs for the year, month and day as
5
+ # well, defaulting to `Time.current` if the form object doesn't have a value, much like Rails'
6
+ # own `time_select`.
7
+ #
8
+ # @see Formtastic::Inputs::Base::Timeish Timeish module for documentation of date, time and datetime input options.
9
+ class TimeSelectInput
10
+ include Base
11
+ include Base::Timeish
12
+
13
+ # we don't want year / month / day fragments if :ignore_date => true
14
+ def fragments
15
+ time_fragments
16
+ end
17
+
18
+ def fragment_value(fragment)
19
+ value ? value.send(fragment) : ""
20
+ end
21
+
22
+ def hidden_fragments
23
+ if !options[:ignore_date]
24
+ date_fragments.map do |fragment|
25
+ template.hidden_field_tag(hidden_field_name(fragment), fragment_value(fragment), :id => fragment_id(fragment), :disabled => input_html_options[:disabled] )
26
+ end.join.html_safe
27
+ else
28
+ super
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module Formtastic
2
- VERSION = "2.1.1"
2
+ VERSION = "2.2.0.rc"
3
3
  end
@@ -1,13 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- # --------------------------------------------------------------------------------------------------
4
- # Please note: If you're subclassing Formtastic::FormBuilder, Formtastic uses
5
- # class_attribute for these configuration attributes instead of the deprecated
6
- # class_inheritable_attribute. The behaviour is slightly different with subclasses (especially
7
- # around attributes with Hash or Array) values, so make sure you understand what's happening.
8
- # See the documentation for class_attribute in ActiveSupport for more information.
9
- # --------------------------------------------------------------------------------------------------
10
-
11
3
  # Set the default text field size when input is a string. Default is nil.
12
4
  # Formtastic::FormBuilder.default_text_field_size = 50
13
5
 
@@ -101,7 +101,27 @@
101
101
  </ol>
102
102
  </fieldset>
103
103
  </li>
104
-
104
+
105
+ <li class="input date_picker optional">
106
+ <label class="label" for="gem_expiry">Expiry date</label>
107
+ <input id="gem_expiry" name="gem[gem_expiry]" type="date" size="10" maxlength="10" min="2012-01-01" max="2012-12-31" step="1" value="2012-01-01">
108
+ </li>
109
+
110
+ <li class="input datetime_picker optional">
111
+ <label class="label" for="gem_expiry">Expiry datetime-local</label>
112
+ <input id="gem_expiry" name="gem[gem_expiry]" type="datetime-local" size="16" maxlength="16" min="2012-01-01T00:00" max="2012-12-31T23:59" step="1800">
113
+ </li>
114
+
115
+ <li class="input datetime_picker optional">
116
+ <label class="label" for="gem_expiry">Expiry datetime</label>
117
+ <input id="gem_expiry" name="gem[gem_expiry]" type="datetime" size="16" maxlength="16" min="2012-01-01T00:00" max="2012-12-31T23:59" step="1800">
118
+ </li>
119
+
120
+ <li class="input time_picker optional">
121
+ <label class="label" for="gem_expiry">Expiry time</label>
122
+ <input id="gem_expiry" name="gem[gem_expiry]" type="time" size="5" maxlength="5" min="T00:00" max="23:59" step="60">
123
+ </li>
124
+
105
125
  <li class="input string stringish optional autofocus" id="gem_autofocus_input">
106
126
  <label class="label" for="gem_autofocus">Autofocus</label>
107
127
  <input id="gem_autofocus" name="gem[autofocus]" type="text" value="The focus is set to this field" autofocus="autofocus">
@@ -101,7 +101,7 @@ describe 'Formtastic::FormBuilder#fields_for' do
101
101
 
102
102
  it 'should render errors on the nested inputs' do
103
103
  @errors = mock('errors')
104
- @errors.stub!(:[]).with(:login).and_return(['oh noes'])
104
+ @errors.stub!(:[]).with(errors_matcher(:login)).and_return(['oh noes'])
105
105
  @bob.stub!(:errors).and_return(@errors)
106
106
 
107
107
  concat(semantic_form_for(@new_post, :namespace => 'context2') do |builder|
@@ -15,7 +15,7 @@ describe Formtastic::InstallGenerator do
15
15
  describe 'config/initializers/formtastic.rb' do
16
16
  subject { file('config/initializers/formtastic.rb') }
17
17
  it { should exist }
18
- it { should contain "# Please note: If you're subclassing Formtastic::FormBuilder" }
18
+ it { should contain "#" }
19
19
  end
20
20
 
21
21
  describe 'lib/templates/erb/scaffold/_form.html.erb' do
@@ -417,17 +417,17 @@ describe 'Formtastic::FormBuilder#input' do
417
417
  default_input_type(:text).should == :text
418
418
  end
419
419
 
420
- it 'should default to :date for :date column types' do
421
- default_input_type(:date).should == :date
420
+ it 'should default to :date_select for :date column types' do
421
+ default_input_type(:date).should == :date_select
422
422
  end
423
423
 
424
- it 'should default to :datetime for :datetime and :timestamp column types' do
425
- default_input_type(:datetime).should == :datetime
426
- default_input_type(:timestamp).should == :datetime
424
+ it 'should default to :datetime_select for :datetime and :timestamp column types' do
425
+ default_input_type(:datetime).should == :datetime_select
426
+ default_input_type(:timestamp).should == :datetime_select
427
427
  end
428
428
 
429
- it 'should default to :time for :time column types' do
430
- default_input_type(:time).should == :time
429
+ it 'should default to :time_select for :time column types' do
430
+ default_input_type(:time).should == :time_select
431
431
  end
432
432
 
433
433
  it 'should default to :boolean for :boolean column types' do
@@ -492,7 +492,7 @@ describe 'Formtastic::FormBuilder#input' do
492
492
  end
493
493
 
494
494
  it 'should call the corresponding input class with .to_html' do
495
- [:select, :time_zone, :radio, :date, :datetime, :time, :boolean, :check_boxes, :hidden, :string, :password, :number, :text, :file].each do |input_style|
495
+ [:select, :time_zone, :radio, :date_select, :datetime_select, :time_select, :boolean, :check_boxes, :hidden, :string, :password, :number, :text, :file].each do |input_style|
496
496
  @new_post.stub!(:generic_column_name)
497
497
  @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
498
498
  semantic_form_for(@new_post) do |builder|
@@ -666,11 +666,13 @@ describe 'Formtastic::FormBuilder#input' do
666
666
  end
667
667
 
668
668
  it 'should have a custom hint class if I ask for one' do
669
- hint_text = "this is the title of the post"
670
- concat(semantic_form_for(@new_post) do |builder|
671
- concat(builder.input(:title, :hint => hint_text, :hint_class => 'custom-hint-class'))
672
- end)
673
- output_buffer.should have_tag("form li p.custom-hint-class", hint_text)
669
+ with_deprecation_silenced do
670
+ hint_text = "this is the title of the post"
671
+ concat(semantic_form_for(@new_post) do |builder|
672
+ concat(builder.input(:title, :hint => hint_text, :hint_class => 'custom-hint-class'))
673
+ end)
674
+ output_buffer.should have_tag("form li p.custom-hint-class", hint_text)
675
+ end
674
676
  end
675
677
 
676
678
  it 'should have a custom hint class defaulted for all forms' do
@@ -728,9 +730,11 @@ describe 'Formtastic::FormBuilder#input' do
728
730
  }
729
731
  }
730
732
  }
731
- concat(semantic_form_for(@new_post) do |builder|
732
- concat(builder.input(:title, :hint => true, :hint_class => 'custom-hint-class'))
733
- end)
733
+ with_deprecation_silenced do
734
+ concat(semantic_form_for(@new_post) do |builder|
735
+ concat(builder.input(:title, :hint => true, :hint_class => 'custom-hint-class'))
736
+ end)
737
+ end
734
738
  output_buffer.should have_tag('form li p.custom-hint-class', @localized_hint_text)
735
739
  end
736
740
  end
@@ -17,7 +17,7 @@ describe 'Formtastic::FormBuilder#semantic_errors' do
17
17
 
18
18
  describe 'when there is only one error on base' do
19
19
  before do
20
- @errors.stub!(:[]).with(:base).and_return(@base_error)
20
+ @errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_error)
21
21
  end
22
22
 
23
23
  it 'should render an unordered list' do
@@ -29,7 +29,7 @@ describe 'Formtastic::FormBuilder#semantic_errors' do
29
29
 
30
30
  describe 'when there is more than one error on base' do
31
31
  before do
32
- @errors.stub!(:[]).with(:base).and_return(@base_errors)
32
+ @errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_errors)
33
33
  end
34
34
 
35
35
  it 'should render an unordered list' do
@@ -44,8 +44,8 @@ describe 'Formtastic::FormBuilder#semantic_errors' do
44
44
 
45
45
  describe 'when there are errors on title' do
46
46
  before do
47
- @errors.stub!(:[]).with(:title).and_return(@title_errors)
48
- @errors.stub!(:[]).with(:base).and_return([])
47
+ @errors.stub!(:[]).with(errors_matcher(:title)).and_return(@title_errors)
48
+ @errors.stub!(:[]).with(errors_matcher(:base)).and_return([])
49
49
  end
50
50
 
51
51
  it 'should render an unordered list' do
@@ -58,8 +58,8 @@ describe 'Formtastic::FormBuilder#semantic_errors' do
58
58
 
59
59
  describe 'when there are errors on title and base' do
60
60
  before do
61
- @errors.stub!(:[]).with(:title).and_return(@title_errors)
62
- @errors.stub!(:[]).with(:base).and_return(@base_error)
61
+ @errors.stub!(:[]).with(errors_matcher(:title)).and_return(@title_errors)
62
+ @errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_error)
63
63
  end
64
64
 
65
65
  it 'should render an unordered list' do
@@ -73,8 +73,8 @@ describe 'Formtastic::FormBuilder#semantic_errors' do
73
73
 
74
74
  describe 'when there are no errors' do
75
75
  before do
76
- @errors.stub!(:[]).with(:title).and_return(nil)
77
- @errors.stub!(:[]).with(:base).and_return(nil)
76
+ @errors.stub!(:[]).with(errors_matcher(:title)).and_return(nil)
77
+ @errors.stub!(:[]).with(errors_matcher(:base)).and_return(nil)
78
78
  end
79
79
 
80
80
  it 'should return nil' do
@@ -86,7 +86,7 @@ describe 'Formtastic::FormBuilder#semantic_errors' do
86
86
 
87
87
  describe 'when there is one error on base and options with class is passed' do
88
88
  before do
89
- @errors.stub!(:[]).with(:base).and_return(@base_error)
89
+ @errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_error)
90
90
  end
91
91
 
92
92
  it 'should render an unordered list with given class' do
@@ -98,7 +98,7 @@ describe 'Formtastic::FormBuilder#semantic_errors' do
98
98
 
99
99
  describe 'when :base is passed in as an argument' do
100
100
  before do
101
- @errors.stub!(:[]).with(:base).and_return(@base_error)
101
+ @errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_error)
102
102
  end
103
103
 
104
104
  it 'should ignore :base and only render base errors once' do
@@ -11,8 +11,11 @@ module TestInputs
11
11
  @method = :title
12
12
  @options = {}
13
13
  @proc = Proc.new {}
14
- @builder = Formtastic::FormBuilder.new(@object_name, @object, @template, @options, @proc)
15
-
14
+ if Rails::VERSION::MAJOR == 4
15
+ @builder = Formtastic::FormBuilder.new(@object_name, @object, @template, @options)
16
+ else
17
+ @builder = Formtastic::FormBuilder.new(@object_name, @object, @template, @options, @proc)
18
+ end
16
19
  [@builder, @template, @object, @object_name, @method, @options]
17
20
  end
18
21
 
@@ -0,0 +1,449 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'date_picker input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ context "with an object" do
14
+ before do
15
+ concat(semantic_form_for(@new_post) do |builder|
16
+ concat(builder.input(:publish_at, :as => :date_picker))
17
+ end)
18
+ end
19
+
20
+ it_should_have_input_wrapper_with_class(:date_picker)
21
+ it_should_have_input_wrapper_with_class(:input)
22
+ it_should_have_input_wrapper_with_class(:stringish)
23
+ it_should_have_input_wrapper_with_id("post_publish_at_input")
24
+ it_should_have_label_with_text(/Publish at/)
25
+ it_should_have_label_for("post_publish_at")
26
+ it_should_have_input_with_id("post_publish_at")
27
+ it_should_have_input_with_type(:date)
28
+ it_should_have_input_with_name("post[publish_at]")
29
+ it_should_apply_custom_input_attributes_when_input_html_provided(:date_picker)
30
+ it_should_apply_custom_for_to_label_when_input_html_id_provided(:date_picker)
31
+ # TODO why does this blow-up it_should_apply_error_logic_for_input_type(:date_picker)
32
+
33
+ end
34
+
35
+ describe "size attribute" do
36
+
37
+ it "defaults to 10 chars (YYYY-YY-YY)" do
38
+ concat(
39
+ semantic_form_for(@new_post) do |f|
40
+ concat(f.input(:publish_at, :as => :date_picker))
41
+ end
42
+ )
43
+ output_buffer.should have_tag "input[size='10']"
44
+ end
45
+
46
+ it "can be set from :input_html options" do
47
+ concat(
48
+ semantic_form_for(@new_post) do |f|
49
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :size => "11" }))
50
+ end
51
+ )
52
+ output_buffer.should have_tag "input[size='11']"
53
+ end
54
+
55
+ it "can be set from options (ignoring input_html)" do
56
+ concat(
57
+ semantic_form_for(@new_post) do |f|
58
+ concat(f.input(:publish_at, :as => :date_picker, :size => '12', :input_html => { :size => "11" }))
59
+ end
60
+ )
61
+ output_buffer.should have_tag "input[size='12']"
62
+ end
63
+
64
+ end
65
+
66
+ describe "maxlength attribute" do
67
+
68
+ it "defaults to 10 chars (YYYY-YY-YY)" do
69
+ concat(
70
+ semantic_form_for(@new_post) do |f|
71
+ concat(f.input(:publish_at, :as => :date_picker))
72
+ end
73
+ )
74
+ output_buffer.should have_tag "input[maxlength='10']"
75
+ end
76
+
77
+ it "can be set from :input_html options" do
78
+ concat(
79
+ semantic_form_for(@new_post) do |f|
80
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :maxlength => "11" }))
81
+ end
82
+ )
83
+ output_buffer.should have_tag "input[maxlength='11']"
84
+ end
85
+
86
+ it "can be set from options (ignoring input_html)" do
87
+ concat(
88
+ semantic_form_for(@new_post) do |f|
89
+ concat(f.input(:publish_at, :as => :date_picker, :maxlength => 12, :input_html => { :maxlength => "11" }))
90
+ end
91
+ )
92
+ output_buffer.should have_tag "input[maxlength='12']"
93
+ end
94
+
95
+ end
96
+
97
+ describe "value attribute" do
98
+
99
+ context "when method returns nil" do
100
+
101
+ it "has no value" do
102
+ concat(
103
+ semantic_form_for(@new_post) do |f|
104
+ concat(f.input(:publish_at, :as => :date_picker ))
105
+ end
106
+ )
107
+ output_buffer.should_not have_tag "li input[value]"
108
+ end
109
+
110
+ it "can be set from :input_html options" do
111
+ concat(
112
+ semantic_form_for(@new_post) do |f|
113
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :value => "1111-11-11" }))
114
+ end
115
+ )
116
+ output_buffer.should have_tag "input[value='1111-11-11']"
117
+ end
118
+
119
+ end
120
+
121
+ context "when method returns a Date" do
122
+
123
+ before do
124
+ @date = Date.new(2000, 11, 11)
125
+ @new_post.stub!(:publish_at).and_return(@date)
126
+ end
127
+
128
+ it "renders the date as YYYY-MM-DD" do
129
+ concat(
130
+ semantic_form_for(@new_post) do |f|
131
+ concat(f.input(:publish_at, :as => :date_picker ))
132
+ end
133
+ )
134
+ output_buffer.should have_tag "input[value='#{@date.to_s}']"
135
+ end
136
+
137
+ it "can be set from :input_html options" do
138
+ concat(
139
+ semantic_form_for(@new_post) do |f|
140
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :value => "1111-11-11" }))
141
+ end
142
+ )
143
+ output_buffer.should have_tag "input[value='1111-11-11']"
144
+ end
145
+
146
+ end
147
+
148
+ context "when method returns a Time" do
149
+
150
+ before do
151
+ @time = Time.utc(2000,11,11,11,11,11)
152
+ @new_post.stub!(:publish_at).and_return(@time)
153
+ end
154
+
155
+ it "renders the time as a YYYY-MM-DD" do
156
+ concat(
157
+ semantic_form_for(@new_post) do |f|
158
+ concat(f.input(:publish_at, :as => :date_picker ))
159
+ end
160
+ )
161
+ output_buffer.should have_tag "input[value='2000-11-11']"
162
+ end
163
+
164
+ it "can be set from :input_html options" do
165
+ concat(
166
+ semantic_form_for(@new_post) do |f|
167
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :value => "1111-11-11" }))
168
+ end
169
+ )
170
+ output_buffer.should have_tag "input[value='1111-11-11']"
171
+ end
172
+
173
+ end
174
+
175
+ context "when method returns an empty String" do
176
+
177
+ before do
178
+ @new_post.stub!(:publish_at).and_return("")
179
+ end
180
+
181
+ it "will be empty" do
182
+ concat(
183
+ semantic_form_for(@new_post) do |f|
184
+ concat(f.input(:publish_at, :as => :date_picker ))
185
+ end
186
+ )
187
+ output_buffer.should have_tag "input[value='']"
188
+ end
189
+
190
+ it "can be set from :input_html options" do
191
+ concat(
192
+ semantic_form_for(@new_post) do |f|
193
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :value => "1111-11-11" }))
194
+ end
195
+ )
196
+ output_buffer.should have_tag "input[value='1111-11-11']"
197
+ end
198
+
199
+ end
200
+
201
+ context "when method returns a String" do
202
+
203
+ before do
204
+ @new_post.stub!(:publish_at).and_return("yeah")
205
+ end
206
+
207
+ it "will be the string" do
208
+ concat(
209
+ semantic_form_for(@new_post) do |f|
210
+ concat(f.input(:publish_at, :as => :date_picker ))
211
+ end
212
+ )
213
+ output_buffer.should have_tag "input[value='yeah']"
214
+ end
215
+
216
+ it "can be set from :input_html options" do
217
+ concat(
218
+ semantic_form_for(@new_post) do |f|
219
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :value => "1111-11-11" }))
220
+ end
221
+ )
222
+ output_buffer.should have_tag "input[value='1111-11-11']"
223
+ end
224
+
225
+ end
226
+
227
+ end
228
+
229
+ describe "min attribute" do
230
+
231
+ it "will be omitted by default" do
232
+ concat(
233
+ semantic_form_for(@new_post) do |f|
234
+ concat(f.input(:publish_at, :as => :date_picker))
235
+ end
236
+ )
237
+ output_buffer.should_not have_tag "input[min]"
238
+ end
239
+
240
+ it "can be set from :input_html options" do
241
+ concat(
242
+ semantic_form_for(@new_post) do |f|
243
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :min => "1970-01-01" }))
244
+ end
245
+ )
246
+ output_buffer.should have_tag "input[min='1970-01-01']"
247
+ end
248
+
249
+ end
250
+
251
+ describe "max attribute" do
252
+
253
+ it "will be omitted by default" do
254
+ concat(
255
+ semantic_form_for(@new_post) do |f|
256
+ concat(f.input(:publish_at, :as => :date_picker))
257
+ end
258
+ )
259
+ output_buffer.should_not have_tag "input[max]"
260
+ end
261
+
262
+ it "can be set from :input_html options" do
263
+ concat(
264
+ semantic_form_for(@new_post) do |f|
265
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :max => "1970-01-01" }))
266
+ end
267
+ )
268
+ output_buffer.should have_tag "input[max='1970-01-01']"
269
+ end
270
+
271
+ end
272
+
273
+ describe "step attribute" do
274
+
275
+ it "defaults to 1" do
276
+ concat(
277
+ semantic_form_for(@new_post) do |f|
278
+ concat(f.input(:publish_at, :as => :date_picker))
279
+ end
280
+ )
281
+ output_buffer.should have_tag "input[step='1']"
282
+ end
283
+
284
+ it "can be set from :input_html options" do
285
+ concat(
286
+ semantic_form_for(@new_post) do |f|
287
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :step => "5" }))
288
+ end
289
+ )
290
+ output_buffer.should have_tag "input[step='5']"
291
+ end
292
+
293
+ describe "macros" do
294
+
295
+ before do
296
+ concat(
297
+ semantic_form_for(@new_post) do |f|
298
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :step => step }))
299
+ end
300
+ )
301
+ end
302
+
303
+ context ":day" do
304
+ let(:step) { :day }
305
+ it "uses 1" do
306
+ output_buffer.should have_tag "input[step='1']"
307
+ end
308
+ end
309
+
310
+ context ":seven_days" do
311
+ let(:step) { :seven_days }
312
+ it "uses 7" do
313
+ output_buffer.should have_tag "input[step='7']"
314
+ end
315
+ end
316
+
317
+ context ":week" do
318
+ let(:step) { :week }
319
+ it "uses 7" do
320
+ output_buffer.should have_tag "input[step='7']"
321
+ end
322
+ end
323
+
324
+ context ":fortnight" do
325
+ let(:step) { :fortnight }
326
+ it "uses 14" do
327
+ output_buffer.should have_tag "input[step='14']"
328
+ end
329
+ end
330
+
331
+ context ":two_weeks" do
332
+ let(:step) { :two_weeks }
333
+ it "uses 14" do
334
+ output_buffer.should have_tag "input[step='14']"
335
+ end
336
+ end
337
+
338
+ context ":four_weeks" do
339
+ let(:step) { :four_weeks }
340
+ it "uses 28" do
341
+ output_buffer.should have_tag "input[step='28']"
342
+ end
343
+ end
344
+
345
+ context ":thirty_days" do
346
+ let(:step) { :thirty_days }
347
+ it "uses 30" do
348
+ output_buffer.should have_tag "input[step='30']"
349
+ end
350
+ end
351
+
352
+ end
353
+
354
+ end
355
+
356
+ describe "placeholder attribute" do
357
+
358
+ it "will be omitted" do
359
+ concat(
360
+ semantic_form_for(@new_post) do |f|
361
+ concat(f.input(:publish_at, :as => :date_picker))
362
+ end
363
+ )
364
+ output_buffer.should_not have_tag "input[placeholder]"
365
+ end
366
+
367
+ it "can be set from :input_html options" do
368
+ concat(
369
+ semantic_form_for(@new_post) do |f|
370
+ concat(f.input(:publish_at, :as => :date_picker, :input_html => { :placeholder => "1970-01-01" }))
371
+ end
372
+ )
373
+ output_buffer.should have_tag "input[placeholder='1970-01-01']"
374
+ end
375
+
376
+ context "with i18n set" do
377
+ before do
378
+ ::I18n.backend.store_translations :en, :formtastic => { :placeholders => { :publish_at => 'YYYY-MM-DD' }}
379
+ end
380
+
381
+ it "can be set with i18n" do
382
+ with_config :i18n_lookups_by_default, true do
383
+ concat(semantic_form_for(@new_post) do |builder|
384
+ concat(builder.input(:publish_at, :as => :date_picker))
385
+ end)
386
+ output_buffer.should have_tag('input[@placeholder="YYYY-MM-DD"]')
387
+ end
388
+ end
389
+
390
+ it "can be set with input_html, trumping i18n" do
391
+ with_config :i18n_lookups_by_default, true do
392
+ concat(semantic_form_for(@new_post) do |builder|
393
+ concat(builder.input(:publish_at, :as => :date_picker, :input_html => { :placeholder => "Something" }))
394
+ end)
395
+ output_buffer.should have_tag('input[@placeholder="Something"]')
396
+ end
397
+ end
398
+ end
399
+
400
+ end
401
+
402
+ describe "when namespace is provided" do
403
+ before do
404
+ concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
405
+ concat(builder.input(:publish_at, :as => :date_picker))
406
+ end)
407
+ end
408
+
409
+ it_should_have_input_wrapper_with_id("context2_post_publish_at_input")
410
+ it_should_have_label_and_input_with_id("context2_post_publish_at")
411
+ end
412
+
413
+ describe "when index is provided" do
414
+ before do
415
+ @output_buffer = ''
416
+ mock_everything
417
+
418
+ concat(semantic_form_for(@new_post) do |builder|
419
+ concat(builder.fields_for(:author, :index => 3) do |author|
420
+ concat(author.input(:created_at, :as => :date_picker))
421
+ end)
422
+ end)
423
+ end
424
+
425
+ it 'should index the id of the wrapper' do
426
+ output_buffer.should have_tag("li#post_author_attributes_3_created_at_input")
427
+ end
428
+
429
+ it 'should index the id of the select tag' do
430
+ output_buffer.should have_tag("input#post_author_attributes_3_created_at")
431
+ end
432
+
433
+ it 'should index the name of the select tag' do
434
+ output_buffer.should have_tag("input[@name='post[author_attributes][3][created_at]']")
435
+ end
436
+ end
437
+
438
+ describe "when required" do
439
+ it "should add the required attribute to the input's html options" do
440
+ with_config :use_required_attribute, true do
441
+ concat(semantic_form_for(@new_post) do |builder|
442
+ concat(builder.input(:publish_at, :as => :date_picker, :required => true))
443
+ end)
444
+ output_buffer.should have_tag("input[@required]")
445
+ end
446
+ end
447
+ end
448
+
449
+ end