formtastic 1.2.4 → 3.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +46 -0
- data/.yardopts +1 -0
- data/Appraisals +43 -0
- data/CHANGELOG +54 -0
- data/DEPRECATIONS +52 -0
- data/Gemfile +3 -0
- data/README.md +629 -0
- data/RELEASE_PROCESS +6 -0
- data/Rakefile +35 -0
- data/app/assets/stylesheets/formtastic.css +289 -0
- data/app/assets/stylesheets/formtastic_ie6.css +33 -0
- data/app/assets/stylesheets/formtastic_ie7.css +23 -0
- data/formtastic.gemspec +42 -0
- data/gemfiles/rails_3.2.gemfile +9 -0
- data/gemfiles/rails_4.0.4.gemfile +8 -0
- data/gemfiles/rails_4.1.gemfile +8 -0
- data/gemfiles/rails_4.2.gemfile +8 -0
- data/gemfiles/rails_4.gemfile +8 -0
- data/gemfiles/rails_5.0.gemfile +8 -0
- data/gemfiles/rails_edge.gemfile +15 -0
- data/lib/formtastic.rb +40 -1945
- data/lib/formtastic/action_class_finder.rb +18 -0
- data/lib/formtastic/actions.rb +11 -0
- data/lib/formtastic/actions/base.rb +156 -0
- data/lib/formtastic/actions/button_action.rb +67 -0
- data/lib/formtastic/actions/buttonish.rb +17 -0
- data/lib/formtastic/actions/input_action.rb +70 -0
- data/lib/formtastic/actions/link_action.rb +88 -0
- data/lib/formtastic/deprecation.rb +42 -0
- data/lib/formtastic/engine.rb +11 -0
- data/lib/formtastic/form_builder.rb +124 -0
- data/lib/formtastic/helpers.rb +16 -0
- data/lib/formtastic/helpers/action_helper.rb +162 -0
- data/lib/formtastic/helpers/actions_helper.rb +168 -0
- data/lib/formtastic/helpers/enum.rb +13 -0
- data/lib/formtastic/helpers/errors_helper.rb +81 -0
- data/lib/formtastic/helpers/fieldset_wrapper.rb +80 -0
- data/lib/formtastic/helpers/file_column_detection.rb +16 -0
- data/lib/formtastic/helpers/form_helper.rb +203 -0
- data/lib/formtastic/helpers/input_helper.rb +407 -0
- data/lib/formtastic/helpers/inputs_helper.rb +411 -0
- data/lib/formtastic/helpers/reflection.rb +37 -0
- data/lib/formtastic/html_attributes.rb +32 -0
- data/lib/formtastic/i18n.rb +4 -2
- data/lib/formtastic/input_class_finder.rb +18 -0
- data/lib/formtastic/inputs.rb +39 -0
- data/lib/formtastic/inputs/base.rb +76 -0
- data/lib/formtastic/inputs/base/associations.rb +31 -0
- data/lib/formtastic/inputs/base/choices.rb +108 -0
- data/lib/formtastic/inputs/base/collections.rb +159 -0
- data/lib/formtastic/inputs/base/database.rb +22 -0
- data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
- data/lib/formtastic/inputs/base/errors.rb +58 -0
- data/lib/formtastic/inputs/base/fileish.rb +23 -0
- data/lib/formtastic/inputs/base/hints.rb +31 -0
- data/lib/formtastic/inputs/base/html.rb +53 -0
- data/lib/formtastic/inputs/base/labelling.rb +52 -0
- data/lib/formtastic/inputs/base/naming.rb +42 -0
- data/lib/formtastic/inputs/base/numeric.rb +50 -0
- data/lib/formtastic/inputs/base/options.rb +17 -0
- data/lib/formtastic/inputs/base/placeholder.rb +17 -0
- data/lib/formtastic/inputs/base/stringish.rb +38 -0
- data/lib/formtastic/inputs/base/timeish.rb +241 -0
- data/lib/formtastic/inputs/base/validations.rb +215 -0
- data/lib/formtastic/inputs/base/wrapping.rb +50 -0
- data/lib/formtastic/inputs/boolean_input.rb +118 -0
- data/lib/formtastic/inputs/check_boxes_input.rb +197 -0
- data/lib/formtastic/inputs/color_input.rb +42 -0
- data/lib/formtastic/inputs/country_input.rb +86 -0
- data/lib/formtastic/inputs/datalist_input.rb +41 -0
- data/lib/formtastic/inputs/date_picker_input.rb +93 -0
- data/lib/formtastic/inputs/date_select_input.rb +34 -0
- data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
- data/lib/formtastic/inputs/datetime_select_input.rb +12 -0
- data/lib/formtastic/inputs/email_input.rb +41 -0
- data/lib/formtastic/inputs/file_input.rb +42 -0
- data/lib/formtastic/inputs/hidden_input.rb +62 -0
- data/lib/formtastic/inputs/number_input.rb +88 -0
- data/lib/formtastic/inputs/password_input.rb +41 -0
- data/lib/formtastic/inputs/phone_input.rb +42 -0
- data/lib/formtastic/inputs/radio_input.rb +163 -0
- data/lib/formtastic/inputs/range_input.rb +95 -0
- data/lib/formtastic/inputs/search_input.rb +41 -0
- data/lib/formtastic/inputs/select_input.rb +235 -0
- data/lib/formtastic/inputs/string_input.rb +36 -0
- data/lib/formtastic/inputs/text_input.rb +48 -0
- data/lib/formtastic/inputs/time_picker_input.rb +99 -0
- data/lib/formtastic/inputs/time_select_input.rb +38 -0
- data/lib/formtastic/inputs/time_zone_input.rb +58 -0
- data/lib/formtastic/inputs/url_input.rb +41 -0
- data/lib/formtastic/localized_string.rb +17 -0
- data/lib/formtastic/localizer.rb +152 -0
- data/lib/formtastic/namespaced_class_finder.rb +99 -0
- data/lib/formtastic/util.rb +35 -16
- data/lib/formtastic/version.rb +3 -0
- data/lib/generators/formtastic/form/form_generator.rb +64 -37
- data/lib/generators/formtastic/input/input_generator.rb +46 -0
- data/lib/generators/formtastic/install/install_generator.rb +13 -5
- data/lib/generators/templates/_form.html.erb +10 -4
- data/lib/generators/templates/_form.html.haml +8 -4
- data/lib/generators/templates/_form.html.slim +8 -0
- data/lib/generators/templates/formtastic.rb +77 -44
- data/lib/generators/templates/input.rb +19 -0
- data/lib/locale/en.yml +3 -0
- data/sample/basic_inputs.html +224 -0
- data/sample/config.ru +69 -0
- data/sample/index.html +14 -0
- data/spec/action_class_finder_spec.rb +12 -0
- data/spec/actions/button_action_spec.rb +63 -0
- data/spec/actions/generic_action_spec.rb +521 -0
- data/spec/actions/input_action_spec.rb +59 -0
- data/spec/actions/link_action_spec.rb +92 -0
- data/spec/builder/custom_builder_spec.rb +116 -0
- data/spec/builder/error_proc_spec.rb +27 -0
- data/spec/builder/semantic_fields_for_spec.rb +142 -0
- data/spec/fast_spec_helper.rb +12 -0
- data/spec/generators/formtastic/form/form_generator_spec.rb +131 -0
- data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
- data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
- data/spec/helpers/action_helper_spec.rb +19 -0
- data/spec/helpers/actions_helper_spec.rb +143 -0
- data/spec/helpers/form_helper_spec.rb +218 -0
- data/spec/helpers/input_helper_spec.rb +6 -0
- data/spec/helpers/inputs_helper_spec.rb +655 -0
- data/spec/helpers/namespaced_action_helper_spec.rb +43 -0
- data/spec/helpers/namespaced_input_helper_spec.rb +36 -0
- data/spec/helpers/reflection_helper_spec.rb +32 -0
- data/spec/helpers/semantic_errors_helper_spec.rb +112 -0
- data/spec/i18n_spec.rb +210 -0
- data/spec/input_class_finder_spec.rb +10 -0
- data/spec/inputs/base/collections_spec.rb +76 -0
- data/spec/inputs/base/validations_spec.rb +342 -0
- data/spec/inputs/boolean_input_spec.rb +254 -0
- data/spec/inputs/check_boxes_input_spec.rb +546 -0
- data/spec/inputs/color_input_spec.rb +97 -0
- data/spec/inputs/country_input_spec.rb +133 -0
- data/spec/inputs/custom_input_spec.rb +55 -0
- data/spec/inputs/datalist_input_spec.rb +61 -0
- data/spec/inputs/date_picker_input_spec.rb +449 -0
- data/spec/inputs/date_select_input_spec.rb +235 -0
- data/spec/inputs/datetime_picker_input_spec.rb +490 -0
- data/spec/inputs/datetime_select_input_spec.rb +193 -0
- data/spec/inputs/email_input_spec.rb +85 -0
- data/spec/inputs/file_input_spec.rb +89 -0
- data/spec/inputs/hidden_input_spec.rb +135 -0
- data/spec/inputs/include_blank_spec.rb +78 -0
- data/spec/inputs/label_spec.rb +149 -0
- data/spec/inputs/number_input_spec.rb +815 -0
- data/spec/inputs/password_input_spec.rb +99 -0
- data/spec/inputs/phone_input_spec.rb +85 -0
- data/spec/inputs/placeholder_spec.rb +71 -0
- data/spec/inputs/radio_input_spec.rb +328 -0
- data/spec/inputs/range_input_spec.rb +505 -0
- data/spec/inputs/readonly_spec.rb +50 -0
- data/spec/inputs/search_input_spec.rb +84 -0
- data/spec/inputs/select_input_spec.rb +615 -0
- data/spec/inputs/string_input_spec.rb +260 -0
- data/spec/inputs/text_input_spec.rb +187 -0
- data/spec/inputs/time_picker_input_spec.rb +455 -0
- data/spec/inputs/time_select_input_spec.rb +248 -0
- data/spec/inputs/time_zone_input_spec.rb +143 -0
- data/spec/inputs/url_input_spec.rb +85 -0
- data/spec/inputs/with_options_spec.rb +43 -0
- data/spec/localizer_spec.rb +130 -0
- data/spec/namespaced_class_finder_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +525 -0
- data/spec/support/custom_macros.rb +564 -0
- data/spec/support/deprecation.rb +6 -0
- data/spec/support/shared_examples.rb +1313 -0
- data/spec/support/specialized_class_finder_shared_example.rb +27 -0
- data/spec/support/test_environment.rb +31 -0
- data/spec/util_spec.rb +66 -0
- metadata +434 -161
- data/README.textile +0 -682
- data/generators/form/USAGE +0 -16
- data/generators/form/form_generator.rb +0 -111
- data/generators/formtastic/formtastic_generator.rb +0 -26
- data/init.rb +0 -5
- data/lib/formtastic/layout_helper.rb +0 -12
- data/lib/formtastic/railtie.rb +0 -14
- data/lib/generators/templates/formtastic.css +0 -145
- data/lib/generators/templates/formtastic_changes.css +0 -14
- data/lib/generators/templates/rails2/_form.html.erb +0 -5
- data/lib/generators/templates/rails2/_form.html.haml +0 -4
- data/rails/init.rb +0 -2
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'fast_spec_helper'
|
|
2
|
+
require 'inputs/base/collections'
|
|
3
|
+
|
|
4
|
+
class MyInput
|
|
5
|
+
include Formtastic::Inputs::Base::Collections
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe MyInput do
|
|
9
|
+
let(:builder) { double }
|
|
10
|
+
let(:template) { double }
|
|
11
|
+
let(:model_class) { double }
|
|
12
|
+
let(:model) { double(:class => model_class) }
|
|
13
|
+
let(:model_name) { "post" }
|
|
14
|
+
let(:method) { double }
|
|
15
|
+
let(:options) { Hash.new }
|
|
16
|
+
|
|
17
|
+
let(:instance) { MyInput.new(builder, template, model, model_name, method, options) }
|
|
18
|
+
|
|
19
|
+
# class Whatever < ActiveRecord::Base
|
|
20
|
+
# enum :status => [:active, :archived]
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# Whatever.statuses
|
|
24
|
+
#
|
|
25
|
+
# Whatever.new.status
|
|
26
|
+
#
|
|
27
|
+
# f.input :status
|
|
28
|
+
describe "#collection_from_enum" do
|
|
29
|
+
|
|
30
|
+
let(:method) { :status }
|
|
31
|
+
|
|
32
|
+
context "when an enum is defined for the method" do
|
|
33
|
+
before do
|
|
34
|
+
statuses = ActiveSupport::HashWithIndifferentAccess.new("active"=>0, "inactive"=>1)
|
|
35
|
+
model_class.stub(:statuses) { statuses }
|
|
36
|
+
model.stub(:defined_enums) { {"status" => statuses } }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'no translations available' do
|
|
40
|
+
it 'returns an Array of EnumOption objects based on the enum options hash' do
|
|
41
|
+
instance.collection_from_enum.should eq [["Active", "active"],["Inactive", "inactive"]]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context 'with translations' do
|
|
46
|
+
before do
|
|
47
|
+
::I18n.backend.store_translations :en, :activerecord => {
|
|
48
|
+
:attributes => {
|
|
49
|
+
:post => {
|
|
50
|
+
:statuses => {
|
|
51
|
+
:active => "I am active",
|
|
52
|
+
:inactive => "I am inactive"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
it 'returns an Array of EnumOption objects based on the enum options hash' do
|
|
59
|
+
instance.collection_from_enum.should eq [["I am active", "active"],["I am inactive", "inactive"]]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
after do
|
|
63
|
+
::I18n.backend.store_translations :en, {}
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context "when an enum is not defined" do
|
|
69
|
+
it 'returns nil' do
|
|
70
|
+
instance.collection_from_enum.should eq nil
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
require 'fast_spec_helper'
|
|
2
|
+
require 'inputs/base/validations'
|
|
3
|
+
|
|
4
|
+
class MyInput
|
|
5
|
+
include Formtastic::Inputs::Base::Validations
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe MyInput do
|
|
9
|
+
let(:builder) { double }
|
|
10
|
+
let(:template) { double }
|
|
11
|
+
let(:model_class) { double }
|
|
12
|
+
let(:model) { double(:class => model_class) }
|
|
13
|
+
let(:model_name) { "post" }
|
|
14
|
+
let(:method) { double }
|
|
15
|
+
let(:options) { Hash.new }
|
|
16
|
+
let(:validator) { double }
|
|
17
|
+
let(:instance) { MyInput.new(builder, template, model, model_name, method, options) }
|
|
18
|
+
|
|
19
|
+
describe '#required?' do
|
|
20
|
+
context 'with a single validator' do
|
|
21
|
+
before :each do
|
|
22
|
+
allow(instance).to receive(:validations?).and_return(:true)
|
|
23
|
+
allow(instance).to receive(:validations).and_return([validator])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'with options[:required] being true' do
|
|
27
|
+
let(:options) { {required: true} }
|
|
28
|
+
|
|
29
|
+
it 'is required' do
|
|
30
|
+
expect(instance.required?).to be_truthy
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context 'with options[:required] being false' do
|
|
35
|
+
let(:options) { {required: false} }
|
|
36
|
+
|
|
37
|
+
it 'is not required' do
|
|
38
|
+
expect(instance.required?).to be_falsey
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'with negated validation' do
|
|
43
|
+
it 'is not required' do
|
|
44
|
+
instance.not_required_through_negated_validation!
|
|
45
|
+
expect(instance.required?).to be_falsey
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context 'with presence validator' do
|
|
50
|
+
let (:validator) { double(options: {}, kind: :presence) }
|
|
51
|
+
|
|
52
|
+
it 'is required' do
|
|
53
|
+
expect(instance.required?).to be_truthy
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'with options[:on] as symbol' do
|
|
57
|
+
context 'with save context' do
|
|
58
|
+
let (:validator) { double(options: {on: :save}, kind: :presence) }
|
|
59
|
+
|
|
60
|
+
it 'is required' do
|
|
61
|
+
expect(instance.required?).to be_truthy
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context 'with create context' do
|
|
66
|
+
let (:validator) { double(options: {on: :create}, kind: :presence) }
|
|
67
|
+
|
|
68
|
+
it 'is required for new records' do
|
|
69
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
70
|
+
expect(instance.required?).to be_truthy
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'is not required for existing records' do
|
|
74
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
75
|
+
expect(instance.required?).to be_falsey
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context 'with update context' do
|
|
80
|
+
let (:validator) { double(options: {on: :update}, kind: :presence) }
|
|
81
|
+
|
|
82
|
+
it 'is not required for new records' do
|
|
83
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
84
|
+
expect(instance.required?).to be_falsey
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'is required for existing records' do
|
|
88
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
89
|
+
expect(instance.required?).to be_truthy
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'with options[:on] as array' do
|
|
95
|
+
context 'with save context' do
|
|
96
|
+
let (:validator) { double(options: {on: [:save]}, kind: :presence) }
|
|
97
|
+
|
|
98
|
+
it 'is required' do
|
|
99
|
+
expect(instance.required?).to be_truthy
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'with create context' do
|
|
104
|
+
let (:validator) { double(options: {on: [:create]}, kind: :presence) }
|
|
105
|
+
|
|
106
|
+
it 'is required for new records' do
|
|
107
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
108
|
+
expect(instance.required?).to be_truthy
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'is not required for existing records' do
|
|
112
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
113
|
+
expect(instance.required?).to be_falsey
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'with update context' do
|
|
118
|
+
let (:validator) { double(options: {on: [:update]}, kind: :presence) }
|
|
119
|
+
|
|
120
|
+
it 'is not required for new records' do
|
|
121
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
122
|
+
expect(instance.required?).to be_falsey
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'is required for existing records' do
|
|
126
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
127
|
+
expect(instance.required?).to be_truthy
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
context 'with save and create context' do
|
|
132
|
+
let (:validator) { double(options: {on: [:save, :create]}, kind: :presence) }
|
|
133
|
+
|
|
134
|
+
it 'is required for new records' do
|
|
135
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
136
|
+
expect(instance.required?).to be_truthy
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'is required for existing records' do
|
|
140
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
141
|
+
expect(instance.required?).to be_truthy
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
context 'with save and update context' do
|
|
146
|
+
let (:validator) { double(options: {on: [:save, :create]}, kind: :presence) }
|
|
147
|
+
|
|
148
|
+
it 'is required for new records' do
|
|
149
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
150
|
+
expect(instance.required?).to be_truthy
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it 'is required for existing records' do
|
|
154
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
155
|
+
expect(instance.required?).to be_truthy
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context 'with create and update context' do
|
|
160
|
+
let (:validator) { double(options: {on: [:create, :update]}, kind: :presence) }
|
|
161
|
+
|
|
162
|
+
it 'is required for new records' do
|
|
163
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
164
|
+
expect(instance.required?).to be_truthy
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it 'is required for existing records' do
|
|
168
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
169
|
+
expect(instance.required?).to be_truthy
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
context 'with save and other context' do
|
|
174
|
+
let (:validator) { double(options: {on: [:save, :foo]}, kind: :presence) }
|
|
175
|
+
|
|
176
|
+
it 'is required for new records' do
|
|
177
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
178
|
+
expect(instance.required?).to be_truthy
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'is required for existing records' do
|
|
182
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
183
|
+
expect(instance.required?).to be_truthy
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
context 'with create and other context' do
|
|
188
|
+
let (:validator) { double(options: {on: [:create, :foo]}, kind: :presence) }
|
|
189
|
+
|
|
190
|
+
it 'is required for new records' do
|
|
191
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
192
|
+
expect(instance.required?).to be_truthy
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'is not required for existing records' do
|
|
196
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
197
|
+
expect(instance.required?).to be_falsey
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
context 'with update and other context' do
|
|
202
|
+
let (:validator) { double(options: {on: [:update, :foo]}, kind: :presence) }
|
|
203
|
+
|
|
204
|
+
it 'is not required for new records' do
|
|
205
|
+
allow(model).to receive(:new_record?).and_return(true)
|
|
206
|
+
expect(instance.required?).to be_falsey
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it 'is required for existing records' do
|
|
210
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
211
|
+
expect(instance.required?).to be_truthy
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
context 'with inclusion validator' do
|
|
218
|
+
context 'with allow blank' do
|
|
219
|
+
let (:validator) { double(options: {allow_blank: true}, kind: :inclusion) }
|
|
220
|
+
|
|
221
|
+
it 'is not required' do
|
|
222
|
+
expect(instance.required?).to be_falsey
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
context 'without allow blank' do
|
|
227
|
+
let (:validator) { double(options: {allow_blank: false}, kind: :inclusion) }
|
|
228
|
+
|
|
229
|
+
it 'is required' do
|
|
230
|
+
expect(instance.required?).to be_truthy
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
context 'with a length validator' do
|
|
236
|
+
context 'with allow blank' do
|
|
237
|
+
let (:validator) { double(options: {allow_blank: true}, kind: :length) }
|
|
238
|
+
|
|
239
|
+
it 'is not required' do
|
|
240
|
+
expect(instance.required?).to be_falsey
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
context 'without allow blank' do
|
|
245
|
+
let (:validator) { double(options: {allow_blank: false}, kind: :length) }
|
|
246
|
+
|
|
247
|
+
it 'is not required' do
|
|
248
|
+
expect(instance.required?).to be_falsey
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
context 'with a minimum > 0' do
|
|
252
|
+
let (:validator) { double(options: {allow_blank: false, minimum: 1}, kind: :length) }
|
|
253
|
+
|
|
254
|
+
it 'is required' do
|
|
255
|
+
expect(instance.required?).to be_truthy
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
context 'with a minimum <= 0' do
|
|
260
|
+
let (:validator) { double(options: {allow_blank: false, minimum: 0}, kind: :length) }
|
|
261
|
+
|
|
262
|
+
it 'is not required' do
|
|
263
|
+
expect(instance.required?).to be_falsey
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context 'with a defined range starting with > 0' do
|
|
268
|
+
let (:validator) { double(options: {allow_blank: false, within: 1..5}, kind: :length) }
|
|
269
|
+
|
|
270
|
+
it 'is required' do
|
|
271
|
+
expect(instance.required?).to be_truthy
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
context 'with a defined range starting with <= 0' do
|
|
276
|
+
let (:validator) { double(options: {allow_blank: false, within: 0..5}, kind: :length) }
|
|
277
|
+
|
|
278
|
+
it 'is not required' do
|
|
279
|
+
expect(instance.required?).to be_falsey
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
context 'with another validator' do
|
|
286
|
+
let (:validator) { double(options: {allow_blank: true}, kind: :foo) }
|
|
287
|
+
|
|
288
|
+
it 'is not required' do
|
|
289
|
+
expect(instance.required?).to be_falsey
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
context 'with multiple validators' do
|
|
295
|
+
context 'with a on create presence validator and a on update presence validator' do
|
|
296
|
+
let (:validator1) { double(options: {on: :create}, kind: :presence) }
|
|
297
|
+
let (:validator2) { double(options: {}, kind: :presence) }
|
|
298
|
+
|
|
299
|
+
before :each do
|
|
300
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
301
|
+
allow(instance).to receive(:validations?).and_return(:true)
|
|
302
|
+
allow(instance).to receive(:validations).and_return([validator1, validator2])
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it 'is required' do
|
|
306
|
+
expect(instance.required?).to be_truthy
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
context 'with a on create presence validator and a presence validator' do
|
|
311
|
+
let (:validator1) { double(options: {on: :create}, kind: :presence) }
|
|
312
|
+
let (:validator2) { double(options: {}, kind: :presence) }
|
|
313
|
+
|
|
314
|
+
before :each do
|
|
315
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
316
|
+
allow(instance).to receive(:validations?).and_return(:true)
|
|
317
|
+
allow(instance).to receive(:validations).and_return([validator1, validator2])
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
it 'is required' do
|
|
321
|
+
expect(instance.required?).to be_truthy
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
context 'with a on create presence validator and a allow blank inclusion validator' do
|
|
326
|
+
let (:validator1) { double(options: {on: :create}, kind: :presence) }
|
|
327
|
+
let (:validator2) { double(options: {allow_blank: true}, kind: :inclusion) }
|
|
328
|
+
|
|
329
|
+
before :each do
|
|
330
|
+
allow(model).to receive(:new_record?).and_return(false)
|
|
331
|
+
allow(instance).to receive(:validations?).and_return(:true)
|
|
332
|
+
allow(instance).to receive(:validations).and_return([validator1, validator2])
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
it 'is required' do
|
|
336
|
+
expect(instance.required?).to be_falsey
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
describe 'boolean input' do
|
|
5
|
+
|
|
6
|
+
include FormtasticSpecHelper
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
@output_buffer = ''
|
|
10
|
+
mock_everything
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe 'generic' do
|
|
14
|
+
before do
|
|
15
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
16
|
+
concat(builder.input(:allow_comments, :as => :boolean))
|
|
17
|
+
end)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it_should_have_input_wrapper_with_class("boolean")
|
|
21
|
+
it_should_have_input_wrapper_with_class(:input)
|
|
22
|
+
it_should_have_input_wrapper_with_id("post_allow_comments_input")
|
|
23
|
+
it_should_apply_error_logic_for_input_type(:boolean)
|
|
24
|
+
|
|
25
|
+
it 'should generate a label containing the input' do
|
|
26
|
+
output_buffer.should_not have_tag('label.label')
|
|
27
|
+
output_buffer.should have_tag('form li label', :count => 1)
|
|
28
|
+
output_buffer.should have_tag('form li label[@for="post_allow_comments"]')
|
|
29
|
+
output_buffer.should have_tag('form li label', /Allow comments/)
|
|
30
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"]', :count => 1)
|
|
31
|
+
output_buffer.should have_tag('form li input[@type="hidden"]', :count => 1)
|
|
32
|
+
output_buffer.should_not have_tag('form li label input[@type="hidden"]', :count => 1) # invalid HTML5
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'should not add a "name" attribute to the label' do
|
|
36
|
+
output_buffer.should_not have_tag('form li label[@name]')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'should generate a checkbox input' do
|
|
40
|
+
output_buffer.should have_tag('form li label input')
|
|
41
|
+
output_buffer.should have_tag('form li label input#post_allow_comments')
|
|
42
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"]')
|
|
43
|
+
output_buffer.should have_tag('form li label input[@name="post[allow_comments]"]')
|
|
44
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"][@value="1"]')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'should generate a checked input if object.method returns true' do
|
|
48
|
+
output_buffer.should have_tag('form li label input[@checked="checked"]')
|
|
49
|
+
output_buffer.should have_tag('form li input[@name="post[allow_comments]"]', :count => 2)
|
|
50
|
+
output_buffer.should have_tag('form li input#post_allow_comments', :count => 1)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'should generate a checked input if :input_html is passed :checked => checked' do
|
|
55
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
56
|
+
concat(builder.input(:answer_comments, :as => :boolean, :input_html => {:checked => 'checked'}))
|
|
57
|
+
end)
|
|
58
|
+
output_buffer.should have_tag('form li label input[@checked="checked"]')
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'should name the hidden input with the :name html_option' do
|
|
62
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
63
|
+
concat(builder.input(:answer_comments, :as => :boolean, :input_html => { :name => "foo" }))
|
|
64
|
+
end)
|
|
65
|
+
|
|
66
|
+
output_buffer.should have_tag('form li input[@type="checkbox"][@name="foo"]', :count => 1)
|
|
67
|
+
output_buffer.should have_tag('form li input[@type="hidden"][@name="foo"]', :count => 1)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'should name the hidden input with the :name html_option' do
|
|
71
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
72
|
+
concat(builder.input(:answer_comments, :as => :boolean, :input_html => { :name => "foo" }))
|
|
73
|
+
end)
|
|
74
|
+
|
|
75
|
+
output_buffer.should have_tag('form li input[@type="checkbox"][@name="foo"]', :count => 1)
|
|
76
|
+
output_buffer.should have_tag('form li input[@type="hidden"][@name="foo"]', :count => 1)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should generate a disabled input and hidden input if :input_html is passed :disabled => 'disabled' " do
|
|
80
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
81
|
+
concat(builder.input(:allow_comments, :as => :boolean, :input_html => {:disabled => 'disabled'}))
|
|
82
|
+
end)
|
|
83
|
+
output_buffer.should have_tag('form li label input[@disabled="disabled"]', :count => 1)
|
|
84
|
+
output_buffer.should have_tag('form li input[@type="hidden"][@disabled="disabled"]', :count => 1)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'should generate an input[id] with matching label[for] when id passed in :input_html' do
|
|
88
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
89
|
+
concat(builder.input(:allow_comments, :as => :boolean, :input_html => {:id => 'custom_id'}))
|
|
90
|
+
end)
|
|
91
|
+
output_buffer.should have_tag('form li label input[@id="custom_id"]')
|
|
92
|
+
output_buffer.should have_tag('form li label[@for="custom_id"]')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'should allow checked and unchecked values to be sent' do
|
|
96
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
97
|
+
concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'checked', :unchecked_value => 'unchecked'))
|
|
98
|
+
end)
|
|
99
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"][@value="checked"]:not([@unchecked_value][@checked_value])')
|
|
100
|
+
output_buffer.should have_tag('form li input[@type="hidden"][@value="unchecked"]')
|
|
101
|
+
output_buffer.should_not have_tag('form li label input[@type="hidden"]') # invalid HTML5
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'should generate a checked input if object.method returns checked value' do
|
|
105
|
+
@new_post.stub(:allow_comments).and_return('yes')
|
|
106
|
+
|
|
107
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
108
|
+
concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
|
|
109
|
+
end)
|
|
110
|
+
|
|
111
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"][@checked="checked"]')
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'should not generate a checked input if object.method returns unchecked value' do
|
|
115
|
+
@new_post.stub(:allow_comments).and_return('no')
|
|
116
|
+
|
|
117
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
118
|
+
concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
|
|
119
|
+
end)
|
|
120
|
+
|
|
121
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"]:not([@checked])')
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'should generate a checked input if object.method returns checked value' do
|
|
125
|
+
@new_post.stub(:allow_comments).and_return('yes')
|
|
126
|
+
|
|
127
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
128
|
+
concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
|
|
129
|
+
end)
|
|
130
|
+
|
|
131
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"][@checked="checked"]')
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'should generate a checked input for boolean database values compared to string checked values' do
|
|
135
|
+
@new_post.stub(:foo).and_return(1)
|
|
136
|
+
|
|
137
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
138
|
+
concat(builder.input(:foo, :as => :boolean))
|
|
139
|
+
end)
|
|
140
|
+
|
|
141
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"][@value="1"][@checked="checked"]')
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'should generate a checked input if object.method returns checked value when inverted' do
|
|
145
|
+
@new_post.stub(:allow_comments).and_return(0)
|
|
146
|
+
|
|
147
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
148
|
+
concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 0, :unchecked_value => 1))
|
|
149
|
+
end)
|
|
150
|
+
|
|
151
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"][@value="0"][@checked="checked"]')
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'should not generate a checked input if object.method returns unchecked value' do
|
|
155
|
+
@new_post.stub(:allow_comments).and_return('no')
|
|
156
|
+
|
|
157
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
158
|
+
concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
|
|
159
|
+
end)
|
|
160
|
+
|
|
161
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"]:not([@checked])')
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it 'should generate a label and a checkbox even if no object is given' do
|
|
165
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
|
166
|
+
concat(builder.input(:allow_comments, :as => :boolean))
|
|
167
|
+
end)
|
|
168
|
+
|
|
169
|
+
output_buffer.should have_tag('form li label[@for="project_allow_comments"]')
|
|
170
|
+
output_buffer.should have_tag('form li label', /Allow comments/)
|
|
171
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"]')
|
|
172
|
+
|
|
173
|
+
output_buffer.should have_tag('form li label input#project_allow_comments')
|
|
174
|
+
output_buffer.should have_tag('form li label input[@type="checkbox"]')
|
|
175
|
+
output_buffer.should have_tag('form li label input[@name="project[allow_comments]"]')
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it 'should not pass input_html options down to the label html' do
|
|
179
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
180
|
+
builder.input(:title, :as => :boolean, :input_html => { :tabindex => 2, :x => "X" })
|
|
181
|
+
end)
|
|
182
|
+
output_buffer.should_not have_tag('label[tabindex]')
|
|
183
|
+
output_buffer.should_not have_tag('label[x]')
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
context "when required" do
|
|
187
|
+
|
|
188
|
+
it "should add the required attribute to the input's html options" do
|
|
189
|
+
with_config :use_required_attribute, true do
|
|
190
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
191
|
+
concat(builder.input(:title, :as => :boolean, :required => true))
|
|
192
|
+
end)
|
|
193
|
+
output_buffer.should have_tag("input[@required]")
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "should not add the required attribute to the boolean fields input's html options" do
|
|
198
|
+
with_config :use_required_attribute, true do
|
|
199
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
200
|
+
concat(builder.input(:title, :as => :boolean))
|
|
201
|
+
end)
|
|
202
|
+
output_buffer.should_not have_tag("input[@required]")
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
describe "when namespace is provided" do
|
|
209
|
+
|
|
210
|
+
before do
|
|
211
|
+
@output_buffer = ''
|
|
212
|
+
mock_everything
|
|
213
|
+
|
|
214
|
+
concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
|
|
215
|
+
concat(builder.input(:allow_comments, :as => :boolean))
|
|
216
|
+
end)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it_should_have_input_wrapper_with_id("context2_post_allow_comments_input")
|
|
220
|
+
it_should_have_an_inline_label_for("context2_post_allow_comments")
|
|
221
|
+
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
describe "when index is provided" do
|
|
225
|
+
|
|
226
|
+
before do
|
|
227
|
+
@output_buffer = ''
|
|
228
|
+
mock_everything
|
|
229
|
+
|
|
230
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
231
|
+
concat(builder.fields_for(:author, :index => 3) do |author|
|
|
232
|
+
concat(author.input(:name, :as => :boolean))
|
|
233
|
+
end)
|
|
234
|
+
end)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it 'should index the id of the wrapper' do
|
|
238
|
+
output_buffer.should have_tag("li#post_author_attributes_3_name_input")
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it 'should index the id of the input tag' do
|
|
242
|
+
output_buffer.should have_tag("input#post_author_attributes_3_name")
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it 'should index the name of the hidden input' do
|
|
246
|
+
output_buffer.should have_tag("input[@type='hidden'][@name='post[author_attributes][3][name]']")
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it 'should index the name of the checkbox input' do
|
|
250
|
+
output_buffer.should have_tag("input[@type='checkbox'][@name='post[author_attributes][3][name]']")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
end
|
|
254
|
+
end
|