formtastic 3.1.3 → 3.1.4
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.
- data/.travis.yml +12 -10
- data/Appraisals +11 -7
- data/CHANGELOG +12 -0
- data/DEPRECATIONS +3 -0
- data/{README.textile → README.md} +629 -616
- data/formtastic.gemspec +3 -3
- data/gemfiles/rails_3.2.gemfile +1 -0
- data/gemfiles/rails_edge.gemfile +5 -0
- data/lib/formtastic.rb +4 -0
- data/lib/formtastic/form_builder.rb +3 -0
- data/lib/formtastic/helpers.rb +1 -1
- data/lib/formtastic/helpers/enum.rb +13 -0
- data/lib/formtastic/helpers/fieldset_wrapper.rb +6 -6
- data/lib/formtastic/helpers/form_helper.rb +1 -1
- data/lib/formtastic/helpers/input_helper.rb +5 -1
- data/lib/formtastic/helpers/inputs_helper.rb +16 -20
- data/lib/formtastic/inputs/base/choices.rb +1 -1
- data/lib/formtastic/inputs/base/collections.rb +41 -4
- data/lib/formtastic/inputs/base/html.rb +7 -6
- data/lib/formtastic/inputs/base/naming.rb +4 -4
- data/lib/formtastic/inputs/base/options.rb +2 -3
- data/lib/formtastic/inputs/base/validations.rb +19 -3
- data/lib/formtastic/inputs/check_boxes_input.rb +10 -2
- data/lib/formtastic/inputs/country_input.rb +3 -1
- data/lib/formtastic/inputs/radio_input.rb +20 -0
- data/lib/formtastic/inputs/select_input.rb +28 -0
- data/lib/formtastic/inputs/time_zone_input.rb +16 -6
- data/lib/formtastic/localizer.rb +15 -15
- data/lib/formtastic/namespaced_class_finder.rb +1 -1
- data/lib/formtastic/version.rb +1 -1
- data/lib/generators/formtastic/form/form_generator.rb +1 -1
- data/lib/generators/formtastic/input/input_generator.rb +46 -0
- data/lib/generators/templates/formtastic.rb +10 -7
- data/lib/generators/templates/input.rb +19 -0
- data/spec/fast_spec_helper.rb +12 -0
- data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
- data/spec/helpers/form_helper_spec.rb +4 -4
- data/spec/inputs/base/collections_spec.rb +76 -0
- data/spec/inputs/base/validations_spec.rb +342 -0
- data/spec/inputs/check_boxes_input_spec.rb +66 -20
- data/spec/inputs/country_input_spec.rb +4 -4
- data/spec/inputs/radio_input_spec.rb +28 -0
- data/spec/inputs/readonly_spec.rb +50 -0
- data/spec/inputs/select_input_spec.rb +71 -11
- data/spec/inputs/time_zone_input_spec.rb +35 -9
- data/spec/spec_helper.rb +2 -30
- data/spec/support/shared_examples.rb +69 -0
- metadata +23 -12
- data/spec/support/deferred_garbage_collection.rb +0 -21
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$LOAD_PATH << 'lib/formtastic'
|
3
|
+
require 'active_support/all'
|
4
|
+
require 'localized_string'
|
5
|
+
require 'inputs'
|
6
|
+
require 'helpers'
|
7
|
+
|
8
|
+
class MyInput
|
9
|
+
include Formtastic::Inputs::Base
|
10
|
+
end
|
11
|
+
|
12
|
+
I18n.enforce_available_locales = false if I18n.respond_to?(:enforce_available_locales)
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'generators/formtastic/input/input_generator'
|
4
|
+
|
5
|
+
describe Formtastic::InputGenerator do
|
6
|
+
include FormtasticSpecHelper
|
7
|
+
|
8
|
+
destination File.expand_path("../../../../../tmp", __FILE__)
|
9
|
+
|
10
|
+
before do
|
11
|
+
prepare_destination
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
FileUtils.rm_rf(File.expand_path("../../../../../tmp", __FILE__))
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'without file name' do
|
19
|
+
it 'should raise Thor::RequiredArgumentMissingError' do
|
20
|
+
lambda { run_generator }.should raise_error(Thor::RequiredArgumentMissingError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "input generator with underscore definition" do
|
25
|
+
before { run_generator %w(hat_size)}
|
26
|
+
|
27
|
+
describe 'generate an input in its respective folder' do
|
28
|
+
subject{ file('app/inputs/hat_size_input.rb')}
|
29
|
+
it { should exist}
|
30
|
+
it { should contain "class HatSizeInput"}
|
31
|
+
it { should contain "def to_html"}
|
32
|
+
it { should contain "include Formtastic::Inputs::Base"}
|
33
|
+
it { should_not contain "super"}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "input generator with camelcase definition" do
|
38
|
+
before { run_generator %w(HatSize)}
|
39
|
+
|
40
|
+
describe 'generate an input in its respective folder' do
|
41
|
+
subject{ file('app/inputs/hat_size_input.rb')}
|
42
|
+
it { should exist}
|
43
|
+
it { should contain "class HatSizeInput"}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "input generator with camelcase Input name sufixed" do
|
48
|
+
before { run_generator %w(HatSizeInput)}
|
49
|
+
|
50
|
+
describe 'generate an input in its respective folder' do
|
51
|
+
subject{ file('app/inputs/hat_size_input.rb')}
|
52
|
+
it { should exist}
|
53
|
+
it { should contain "class HatSizeInput"}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "input generator with underscore _input name sufixed" do
|
58
|
+
before { run_generator %w(hat_size_input)}
|
59
|
+
|
60
|
+
describe 'generate an input in its respective folder' do
|
61
|
+
subject{ file('app/inputs/hat_size_input.rb')}
|
62
|
+
it { should exist}
|
63
|
+
it { should contain "class HatSizeInput"}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "input generator with underscore input name sufixed" do
|
68
|
+
before { run_generator %w(hat_sizeinput)}
|
69
|
+
|
70
|
+
describe 'generate an input in its respective folder' do
|
71
|
+
subject{ file('app/inputs/hat_size_input.rb')}
|
72
|
+
it { should exist}
|
73
|
+
it { should contain "class HatSizeInput"}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "override an existing input using extend" do
|
78
|
+
before { run_generator %w(string --extend)}
|
79
|
+
|
80
|
+
describe 'app/inputs/string_input.rb' do
|
81
|
+
subject{ file('app/inputs/string_input.rb')}
|
82
|
+
it { should exist }
|
83
|
+
it { should contain "class StringInput < Formtastic::Inputs::StringInput" }
|
84
|
+
it { should contain "def to_html" }
|
85
|
+
it { should_not contain "include Formtastic::Inputs::Base" }
|
86
|
+
it { should contain "super" }
|
87
|
+
it { should_not contain "def input_html_options" }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "extend an existing input" do
|
92
|
+
before { run_generator %w(FlexibleText --extend string)}
|
93
|
+
|
94
|
+
describe 'app/inputs/flexible_text_input.rb' do
|
95
|
+
subject{ file('app/inputs/flexible_text_input.rb')}
|
96
|
+
it { should contain "class FlexibleTextInput < Formtastic::Inputs::StringInput" }
|
97
|
+
it { should contain "def input_html_options" }
|
98
|
+
it { should_not contain "include Formtastic::Inputs::Base" }
|
99
|
+
it { should_not contain "def to_html" }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "provide a slashed namespace" do
|
104
|
+
before { run_generator %w(stuff/foo)}
|
105
|
+
|
106
|
+
describe 'app/inputs/stuff/foo_input.rb' do
|
107
|
+
subject{ file('app/inputs/stuff/foo_input.rb')}
|
108
|
+
it {should exist}
|
109
|
+
it { should contain "class Stuff::FooInput" }
|
110
|
+
it { should contain "include Formtastic::Inputs::Base" }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "provide a camelized namespace" do
|
115
|
+
before { run_generator %w(Stuff::Foo)}
|
116
|
+
|
117
|
+
describe 'app/inputs/stuff/foo_input.rb' do
|
118
|
+
subject{ file('app/inputs/stuff/foo_input.rb')}
|
119
|
+
it {should exist}
|
120
|
+
it { should contain "class Stuff::FooInput" }
|
121
|
+
it { should contain "include Formtastic::Inputs::Base" }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -24,7 +24,7 @@ describe 'FormHelper' do
|
|
24
24
|
output_buffer.should have_tag("form.formtastic")
|
25
25
|
end
|
26
26
|
|
27
|
-
it '
|
27
|
+
it 'does not add "novalidate" attribute to the generated form when configured to do so' do
|
28
28
|
with_config :perform_browser_validations, true do
|
29
29
|
concat(semantic_form_for(@new_post, :url => '/hello') do |builder|
|
30
30
|
end)
|
@@ -32,7 +32,7 @@ describe 'FormHelper' do
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
it '
|
35
|
+
it 'adds "novalidate" attribute to the generated form when configured to do so' do
|
36
36
|
with_config :perform_browser_validations, false do
|
37
37
|
concat(semantic_form_for(@new_post, :url => '/hello') do |builder|
|
38
38
|
end)
|
@@ -40,7 +40,7 @@ describe 'FormHelper' do
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
it 'allows form HTML to override "novalidate" attribute when
|
43
|
+
it 'allows form HTML to override "novalidate" attribute when configured to validate' do
|
44
44
|
with_config :perform_browser_validations, false do
|
45
45
|
concat(semantic_form_for(@new_post, :url => '/hello', :html => { :novalidate => true }) do |builder|
|
46
46
|
end)
|
@@ -48,7 +48,7 @@ describe 'FormHelper' do
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
it 'allows form HTML to override "novalidate" attribute when
|
51
|
+
it 'allows form HTML to override "novalidate" attribute when configured to not validate' do
|
52
52
|
with_config :perform_browser_validations, true do
|
53
53
|
concat(semantic_form_for(@new_post, :url => '/hello', :html => { :novalidate => false }) do |builder|
|
54
54
|
end)
|
@@ -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
|
+
|