ehoch_simple_form 2.0.2.dev

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/CHANGELOG.md +257 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +797 -0
  4. data/lib/generators/simple_form/USAGE +3 -0
  5. data/lib/generators/simple_form/install_generator.rb +32 -0
  6. data/lib/generators/simple_form/templates/README +12 -0
  7. data/lib/generators/simple_form/templates/_form.html.erb +13 -0
  8. data/lib/generators/simple_form/templates/_form.html.haml +10 -0
  9. data/lib/generators/simple_form/templates/_form.html.slim +10 -0
  10. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb.tt +181 -0
  11. data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +26 -0
  12. data/lib/simple_form.rb +215 -0
  13. data/lib/simple_form/action_view_extensions/builder.rb +338 -0
  14. data/lib/simple_form/action_view_extensions/form_helper.rb +74 -0
  15. data/lib/simple_form/components.rb +20 -0
  16. data/lib/simple_form/components/errors.rb +35 -0
  17. data/lib/simple_form/components/hints.rb +18 -0
  18. data/lib/simple_form/components/html5.rb +26 -0
  19. data/lib/simple_form/components/label_input.rb +15 -0
  20. data/lib/simple_form/components/labels.rb +79 -0
  21. data/lib/simple_form/components/maxlength.rb +41 -0
  22. data/lib/simple_form/components/min_max.rb +50 -0
  23. data/lib/simple_form/components/pattern.rb +34 -0
  24. data/lib/simple_form/components/placeholders.rb +16 -0
  25. data/lib/simple_form/components/readonly.rb +22 -0
  26. data/lib/simple_form/core_ext/hash.rb +16 -0
  27. data/lib/simple_form/error_notification.rb +48 -0
  28. data/lib/simple_form/form_builder.rb +472 -0
  29. data/lib/simple_form/helpers.rb +12 -0
  30. data/lib/simple_form/helpers/autofocus.rb +11 -0
  31. data/lib/simple_form/helpers/disabled.rb +15 -0
  32. data/lib/simple_form/helpers/readonly.rb +15 -0
  33. data/lib/simple_form/helpers/required.rb +35 -0
  34. data/lib/simple_form/helpers/validators.rb +44 -0
  35. data/lib/simple_form/i18n_cache.rb +22 -0
  36. data/lib/simple_form/inputs.rb +21 -0
  37. data/lib/simple_form/inputs/base.rb +162 -0
  38. data/lib/simple_form/inputs/block_input.rb +14 -0
  39. data/lib/simple_form/inputs/boolean_input.rb +64 -0
  40. data/lib/simple_form/inputs/collection_check_boxes_input.rb +21 -0
  41. data/lib/simple_form/inputs/collection_input.rb +101 -0
  42. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +63 -0
  43. data/lib/simple_form/inputs/collection_select_input.rb +14 -0
  44. data/lib/simple_form/inputs/date_time_input.rb +28 -0
  45. data/lib/simple_form/inputs/file_input.rb +9 -0
  46. data/lib/simple_form/inputs/grouped_collection_select_input.rb +41 -0
  47. data/lib/simple_form/inputs/hidden_input.rb +17 -0
  48. data/lib/simple_form/inputs/numeric_input.rb +24 -0
  49. data/lib/simple_form/inputs/password_input.rb +12 -0
  50. data/lib/simple_form/inputs/priority_input.rb +24 -0
  51. data/lib/simple_form/inputs/range_input.rb +14 -0
  52. data/lib/simple_form/inputs/string_input.rb +23 -0
  53. data/lib/simple_form/inputs/text_input.rb +11 -0
  54. data/lib/simple_form/map_type.rb +16 -0
  55. data/lib/simple_form/version.rb +3 -0
  56. data/lib/simple_form/wrappers.rb +8 -0
  57. data/lib/simple_form/wrappers/builder.rb +103 -0
  58. data/lib/simple_form/wrappers/many.rb +69 -0
  59. data/lib/simple_form/wrappers/root.rb +34 -0
  60. data/lib/simple_form/wrappers/single.rb +18 -0
  61. data/test/action_view_extensions/builder_test.rb +577 -0
  62. data/test/action_view_extensions/form_helper_test.rb +104 -0
  63. data/test/components/label_test.rb +310 -0
  64. data/test/form_builder/association_test.rb +177 -0
  65. data/test/form_builder/button_test.rb +47 -0
  66. data/test/form_builder/error_notification_test.rb +79 -0
  67. data/test/form_builder/error_test.rb +121 -0
  68. data/test/form_builder/general_test.rb +356 -0
  69. data/test/form_builder/hint_test.rb +139 -0
  70. data/test/form_builder/input_field_test.rb +63 -0
  71. data/test/form_builder/label_test.rb +71 -0
  72. data/test/form_builder/wrapper_test.rb +149 -0
  73. data/test/generators/simple_form_generator_test.rb +32 -0
  74. data/test/inputs/boolean_input_test.rb +108 -0
  75. data/test/inputs/collection_check_boxes_input_test.rb +224 -0
  76. data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
  77. data/test/inputs/collection_select_input_test.rb +241 -0
  78. data/test/inputs/datetime_input_test.rb +99 -0
  79. data/test/inputs/disabled_test.rb +38 -0
  80. data/test/inputs/discovery_test.rb +61 -0
  81. data/test/inputs/file_input_test.rb +16 -0
  82. data/test/inputs/general_test.rb +69 -0
  83. data/test/inputs/grouped_collection_select_input_test.rb +118 -0
  84. data/test/inputs/hidden_input_test.rb +30 -0
  85. data/test/inputs/numeric_input_test.rb +173 -0
  86. data/test/inputs/priority_input_test.rb +43 -0
  87. data/test/inputs/readonly_test.rb +61 -0
  88. data/test/inputs/required_test.rb +113 -0
  89. data/test/inputs/string_input_test.rb +140 -0
  90. data/test/inputs/text_input_test.rb +24 -0
  91. data/test/simple_form_test.rb +9 -0
  92. data/test/support/discovery_inputs.rb +21 -0
  93. data/test/support/misc_helpers.rb +102 -0
  94. data/test/support/mock_controller.rb +24 -0
  95. data/test/support/models.rb +210 -0
  96. data/test/test_helper.rb +90 -0
  97. metadata +210 -0
@@ -0,0 +1,139 @@
1
+ require 'test_helper'
2
+
3
+ # Tests for f.hint
4
+ class HintTest < ActionView::TestCase
5
+ def with_hint_for(object, *args)
6
+ with_concat_form_for(object) do |f|
7
+ f.hint(*args)
8
+ end
9
+ end
10
+
11
+ test 'hint should not be generated by default' do
12
+ with_hint_for @user, :name
13
+ assert_no_select 'span.hint'
14
+ end
15
+
16
+ test 'hint should be generated with optional text' do
17
+ with_hint_for @user, :name, :hint => 'Use with care...'
18
+ assert_select 'span.hint', 'Use with care...'
19
+ end
20
+
21
+ test 'hint should not modify the options hash' do
22
+ options = { :hint => 'Use with care...' }
23
+ with_hint_for @user, :name, options
24
+ assert_select 'span.hint', 'Use with care...'
25
+ assert_equal({ :hint => 'Use with care...' }, options)
26
+ end
27
+
28
+ test 'hint should be generated cleanly with optional text' do
29
+ with_hint_for @user, :name, :hint => 'Use with care...', :hint_tag => :span
30
+ assert_no_select 'span.hint[hint]'
31
+ assert_no_select 'span.hint[hint_tag]'
32
+ assert_no_select 'span.hint[hint_html]'
33
+ end
34
+
35
+ test 'hint uses the current component tag set' do
36
+ with_hint_for @user, :name, :hint => 'Use with care...', :hint_tag => :p
37
+ assert_select 'p.hint', 'Use with care...'
38
+ end
39
+
40
+ test 'hint should be able to pass html options' do
41
+ with_hint_for @user, :name, :hint => 'Yay!', :id => 'hint', :class => 'yay'
42
+ assert_select 'span#hint.hint.yay'
43
+ end
44
+
45
+ test 'hint should be output as html_safe' do
46
+ with_hint_for @user, :name, :hint => '<b>Bold</b> and not...'
47
+ assert_select 'span.hint', 'Bold and not...'
48
+ end
49
+
50
+
51
+ # Without attribute name
52
+
53
+ test 'hint without attribute name' do
54
+ with_hint_for @validating_user, 'Hello World!'
55
+ assert_select 'span.hint', 'Hello World!'
56
+ end
57
+
58
+ test 'hint without attribute name should generate component tag with a clean HTML' do
59
+ with_hint_for @validating_user, 'Hello World!'
60
+ assert_no_select 'span.hint[hint]'
61
+ assert_no_select 'span.hint[hint_html]'
62
+ end
63
+
64
+ test 'hint without attribute name uses the current component tag set' do
65
+ with_hint_for @user, 'Hello World!', :hint_tag => :p
66
+ assert_no_select 'p.hint[hint]'
67
+ assert_no_select 'p.hint[hint_html]'
68
+ assert_no_select 'p.hint[hint_tag]'
69
+ end
70
+
71
+ test 'hint without attribute name should be able to pass html options' do
72
+ with_hint_for @user, 'Yay', :id => 'hint', :class => 'yay'
73
+ assert_select 'span#hint.hint.yay', 'Yay'
74
+ end
75
+
76
+ # I18n
77
+
78
+ test 'hint should use i18n based on model, action, and attribute to lookup translation' do
79
+ store_translations(:en, :simple_form => { :hints => { :user => {
80
+ :edit => { :name => 'Content of this input will be truncated...' }
81
+ } } }) do
82
+ with_hint_for @user, :name
83
+ assert_select 'span.hint', 'Content of this input will be truncated...'
84
+ end
85
+ end
86
+
87
+ test 'hint should use i18n with model and attribute to lookup translation' do
88
+ store_translations(:en, :simple_form => { :hints => { :user => {
89
+ :name => 'Content of this input will be capitalized...'
90
+ } } }) do
91
+ with_hint_for @user, :name
92
+ assert_select 'span.hint', 'Content of this input will be capitalized...'
93
+ end
94
+ end
95
+
96
+ test 'hint should use i18n under defaults namespace to lookup translation' do
97
+ store_translations(:en, :simple_form => {
98
+ :hints => {:defaults => {:name => 'Content of this input will be downcased...' } }
99
+ }) do
100
+ with_hint_for @user, :name
101
+ assert_select 'span.hint', 'Content of this input will be downcased...'
102
+ end
103
+ end
104
+
105
+ test 'hint should use i18n with lookup for association name' do
106
+ store_translations(:en, :simple_form => { :hints => {
107
+ :user => { :company => 'My company!' }
108
+ } } ) do
109
+ with_hint_for @user, :company_id, :as => :string, :reflection => Association.new(Company, :company, {})
110
+ assert_select 'span.hint', /My company!/
111
+ end
112
+ end
113
+
114
+ test 'hint should output translations as html_safe' do
115
+ store_translations(:en, :simple_form => { :hints => { :user => {
116
+ :edit => { :name => '<b>This is bold</b> and this is not...' }
117
+ } } }) do
118
+ with_hint_for @user, :name
119
+ assert_select 'span.hint', 'This is bold and this is not...'
120
+ end
121
+ end
122
+
123
+
124
+ # No object
125
+
126
+ test 'hint should generate properly when object is not present' do
127
+ with_hint_for :project, :name, :hint => 'Test without object'
128
+ assert_select 'span.hint', 'Test without object'
129
+ end
130
+
131
+ # Custom wrappers
132
+
133
+ test 'hint with custom wrappers works' do
134
+ swap_wrapper do
135
+ with_hint_for @user, :name, :hint => "can't be blank"
136
+ assert_select 'div.omg_hint', "can't be blank"
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,63 @@
1
+ require 'test_helper'
2
+
3
+ # Tests for f.input_field
4
+ class InputFieldTest < ActionView::TestCase
5
+ test "builder input_field should only render the input tag, nothing else" do
6
+ with_concat_form_for(@user) do |f|
7
+ f.input_field :name
8
+ end
9
+ assert_select 'form > input.required.string'
10
+ assert_no_select 'div.string'
11
+ assert_no_select 'label'
12
+ assert_no_select '.hint'
13
+ end
14
+
15
+ test 'builder input_field should allow overriding default input type' do
16
+ with_concat_form_for(@user) do |f|
17
+ f.input_field :name, :as => :text
18
+ end
19
+
20
+ assert_no_select 'input#user_name'
21
+ assert_select 'textarea#user_name.text'
22
+ end
23
+
24
+ test 'builder input_field should allow passing options to input tag' do
25
+ with_concat_form_for(@user) do |f|
26
+ f.input_field :name, :id => 'name_input', :class => 'name'
27
+ end
28
+
29
+ assert_select 'input.string.name#name_input'
30
+ end
31
+
32
+ test 'builder input_field should not modify the options hash' do
33
+ options = { :id => 'name_input', :class => 'name' }
34
+
35
+ with_concat_form_for(@user) do |f|
36
+ f.input_field :name, options
37
+ end
38
+
39
+ assert_select 'input.string.name#name_input'
40
+ assert_equal({ :id => 'name_input', :class => 'name' }, options)
41
+ end
42
+
43
+
44
+ test 'builder input_field should generate an input tag with a clean HTML' do
45
+ with_concat_form_for(@user) do |f|
46
+ f.input_field :name, :as => :integer, :class => 'name'
47
+ end
48
+
49
+ assert_no_select 'input.integer[input_html]'
50
+ assert_no_select 'input.integer[as]'
51
+ end
52
+
53
+ test 'builder collection input_field should generate input tag with a clean HTML' do
54
+ with_concat_form_for(@user) do |f|
55
+ f.input_field :status, :collection => ['Open', 'Closed'], :class => 'status', :label_method => :to_s, :value_method => :to_s
56
+ end
57
+
58
+ assert_no_select 'select.status[input_html]'
59
+ assert_no_select 'select.status[collection]'
60
+ assert_no_select 'select.status[label_method]'
61
+ assert_no_select 'select.status[value_method]'
62
+ end
63
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ class LabelTest < ActionView::TestCase
5
+ def with_label_for(object, *args, &block)
6
+ with_concat_form_for(object) do |f|
7
+ f.label(*args, &block)
8
+ end
9
+ end
10
+
11
+ test 'builder should generate a label for the attribute' do
12
+ with_label_for @user, :name
13
+ assert_select 'label.string[for=user_name]', /Name/
14
+ end
15
+
16
+ test 'builder should generate a label for the boolean attrbiute' do
17
+ with_label_for @user, :name, :as => :boolean
18
+ assert_select 'label.boolean[for=user_name]', /Name/
19
+ assert_no_select 'label[as=boolean]'
20
+ end
21
+
22
+ test 'builder should generate a label componet tag with a clean HTML' do
23
+ with_label_for @user, :name
24
+ assert_no_select 'label.string[label_html]'
25
+ end
26
+
27
+ test 'builder should add a required class to label if the attribute is required' do
28
+ with_label_for @validating_user, :name
29
+ assert_select 'label.string.required[for=validating_user_name]', /Name/
30
+ end
31
+
32
+ test 'builder should allow passing options to label tag' do
33
+ with_label_for @user, :name, :label => 'My label', :id => 'name_label'
34
+ assert_select 'label.string#name_label', /My label/
35
+ end
36
+
37
+ test 'builder label should generate label tag with clean HTML' do
38
+ with_label_for @user, :name, :label => 'My label', :required => true, :id => 'name_label'
39
+ assert_select 'label.string#name_label', /My label/
40
+ assert_no_select 'label[label]'
41
+ assert_no_select 'label[required]'
42
+ end
43
+
44
+ test 'builder should not modify the options hash' do
45
+ options = { :label => 'My label', :id => 'name_label' }
46
+ with_label_for @user, :name, options
47
+ assert_select 'label.string#name_label', /My label/
48
+ assert_equal({ :label => 'My label', :id => 'name_label' }, options)
49
+ end
50
+
51
+ test 'builder should fallback to default label when string is given' do
52
+ with_label_for @user, :name, 'Nome do usuário'
53
+ assert_select 'label', 'Nome do usuário'
54
+ assert_no_select 'label.string'
55
+ end
56
+
57
+ test 'builder should fallback to default label when block is given' do
58
+ with_label_for @user, :name do
59
+ 'Nome do usuário'
60
+ end
61
+ assert_select 'label', 'Nome do usuário'
62
+ assert_no_select 'label.string'
63
+ end
64
+
65
+ test 'builder allows label order to be changed' do
66
+ swap SimpleForm, :label_text => lambda { |l, r| "#{l}:" } do
67
+ with_label_for @user, :age
68
+ assert_select 'label.integer[for=user_age]', "Age:"
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,149 @@
1
+ require 'test_helper'
2
+
3
+ class WrapperTest < ActionView::TestCase
4
+ test 'wrapper should not have error class for attribute without errors' do
5
+ with_form_for @user, :active
6
+ assert_no_select 'div.field_with_errors'
7
+ end
8
+
9
+ test 'wrapper should not have error class when object is not present' do
10
+ with_form_for :project, :name
11
+ assert_no_select 'div.field_with_errors'
12
+ end
13
+
14
+ test 'wrapper should add error class for attribute with errors' do
15
+ with_form_for @user, :name
16
+ assert_select 'div.field_with_errors'
17
+ end
18
+
19
+ test 'wrapper should add hint class for attribute with a hint' do
20
+ with_form_for @user, :name, :hint => 'hint'
21
+ assert_select 'div.field_with_hint'
22
+ end
23
+
24
+ test 'wrapper should not have disabled class by default' do
25
+ with_form_for @user, :active
26
+ assert_no_select 'div.disabled'
27
+ end
28
+
29
+ test 'wrapper should have disabled class when input is disabled' do
30
+ with_form_for @user, :active, :disabled => true
31
+ assert_select 'div.disabled'
32
+ end
33
+
34
+ test 'wrapper should support no wrapping when wrapper is false' do
35
+ with_form_for @user, :name, :wrapper => false
36
+ assert_select 'form > label[for=user_name]'
37
+ assert_select 'form > input#user_name.string'
38
+ end
39
+
40
+ test 'wrapper should support no wrapping when wrapper tag is false' do
41
+ with_form_for @user, :name, :wrapper => custom_wrapper_without_top_level
42
+ assert_select 'form > label[for=user_name]'
43
+ assert_select 'form > input#user_name.string'
44
+ end
45
+
46
+ test 'wrapper should wrapping tag adds required/optional css classes' do
47
+ with_form_for @user, :name
48
+ assert_select 'form div.input.required.string'
49
+
50
+ with_form_for @user, :age, :required => false
51
+ assert_select 'form div.input.optional.integer'
52
+ end
53
+
54
+ test 'wrapper should allow custom options to be given' do
55
+ with_form_for @user, :name, :wrapper_html => { :id => "super_cool", :class => 'yay' }
56
+ assert_select 'form #super_cool.required.string.yay'
57
+ end
58
+
59
+ test 'wrapper should allow tag to be given on demand' do
60
+ with_form_for @user, :name, :wrapper_tag => :b
61
+ assert_select 'form b.required.string'
62
+ end
63
+
64
+ test 'wrapper should allow wrapper class to be given on demand' do
65
+ with_form_for @user, :name, :wrapper_class => :wrapper
66
+ assert_select 'form div.wrapper.required.string'
67
+ end
68
+
69
+ test 'wrapper should skip additional classes when configured' do
70
+ swap SimpleForm, :generate_additional_classes_for => [:input, :label] do
71
+ with_form_for @user, :name, :wrapper_class => :wrapper
72
+ assert_select 'form div.wrapper'
73
+ assert_no_select 'div.required'
74
+ assert_no_select 'div.string'
75
+ end
76
+ end
77
+
78
+ # Custom wrapper test
79
+
80
+ test 'custom wrappers works' do
81
+ swap_wrapper do
82
+ with_form_for @user, :name, :hint => "cool"
83
+ assert_select "section.custom_wrapper div.another_wrapper label"
84
+ assert_select "section.custom_wrapper div.another_wrapper input.string"
85
+ assert_no_select "section.custom_wrapper div.another_wrapper span.omg_error"
86
+ assert_select "section.custom_wrapper div.error_wrapper span.omg_error"
87
+ assert_select "section.custom_wrapper > div.omg_hint", "cool"
88
+ end
89
+ end
90
+
91
+ test 'custom wrappers can be turned off' do
92
+ swap_wrapper do
93
+ with_form_for @user, :name, :another => false
94
+ assert_no_select "section.custom_wrapper div.another_wrapper label"
95
+ assert_no_select "section.custom_wrapper div.another_wrapper input.string"
96
+ assert_select "section.custom_wrapper div.error_wrapper span.omg_error"
97
+ end
98
+ end
99
+
100
+ test 'custom wrappers on a form basis' do
101
+ swap_wrapper :another do
102
+ concat simple_form_for(@user) { |f|
103
+ f.input :name
104
+ }
105
+
106
+ assert_no_select "section.custom_wrapper div.another_wrapper label"
107
+ assert_no_select "section.custom_wrapper div.another_wrapper input.string"
108
+
109
+ concat simple_form_for(@user, :wrapper => :another) { |f|
110
+ f.input :name
111
+ }
112
+
113
+ assert_select "section.custom_wrapper div.another_wrapper label"
114
+ assert_select "section.custom_wrapper div.another_wrapper input.string"
115
+ end
116
+ end
117
+
118
+ test 'custom wrappers on input basis' do
119
+ swap_wrapper :another do
120
+ with_form_for @user, :name
121
+ assert_no_select "section.custom_wrapper div.another_wrapper label"
122
+ assert_no_select "section.custom_wrapper div.another_wrapper input.string"
123
+ output_buffer.replace ""
124
+
125
+ with_form_for @user, :name, :wrapper => :another
126
+ assert_select "section.custom_wrapper div.another_wrapper label"
127
+ assert_select "section.custom_wrapper div.another_wrapper input.string"
128
+ output_buffer.replace ""
129
+ end
130
+
131
+ with_form_for @user, :name, :wrapper => custom_wrapper
132
+ assert_select "section.custom_wrapper div.another_wrapper label"
133
+ assert_select "section.custom_wrapper div.another_wrapper input.string"
134
+ end
135
+
136
+ test 'access wrappers with indifferent access' do
137
+ swap_wrapper :another do
138
+ with_form_for @user, :name, :wrapper => "another"
139
+ assert_select "section.custom_wrapper div.another_wrapper label"
140
+ assert_select "section.custom_wrapper div.another_wrapper input.string"
141
+ end
142
+ end
143
+
144
+ test 'raise error when wrapper not found' do
145
+ assert_raise SimpleForm::WrapperNotFound do
146
+ with_form_for @user, :name, :wrapper => :not_found
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ class SimpleFormGeneratorTest < Rails::Generators::TestCase
4
+ tests SimpleForm::Generators::InstallGenerator
5
+ destination File.expand_path('../../tmp', __FILE__)
6
+ setup :prepare_destination
7
+ teardown { rm_rf(destination_root) }
8
+
9
+ test 'generates example locale file' do
10
+ run_generator
11
+ assert_file 'config/locales/simple_form.en.yml'
12
+ end
13
+
14
+ test 'generates the simple_form initializer' do
15
+ run_generator
16
+ assert_file 'config/initializers/simple_form.rb',
17
+ /config\.default_wrapper = :default/, /config\.boolean_style = :nested/
18
+ end
19
+
20
+ test 'generates the simple_form initializer with the bootstrap wrappers' do
21
+ run_generator %w(--bootstrap)
22
+ assert_file 'config/initializers/simple_form.rb', /config\.wrappers :bootstrap/,
23
+ /config\.default_wrapper = :bootstrap/
24
+ end
25
+
26
+ %W(erb haml slim).each do |engine|
27
+ test "generates the scaffold template when using #{engine}" do
28
+ run_generator ['-e', engine]
29
+ assert_file "lib/templates/#{engine}/scaffold/_form.html.#{engine}"
30
+ end
31
+ end
32
+ end