sp-validates_timeliness 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +183 -0
  3. data/LICENSE +20 -0
  4. data/README.md +323 -0
  5. data/Rakefile +30 -0
  6. data/init.rb +1 -0
  7. data/lib/generators/validates_timeliness/install_generator.rb +16 -0
  8. data/lib/generators/validates_timeliness/templates/en.yml +16 -0
  9. data/lib/generators/validates_timeliness/templates/validates_timeliness.rb +40 -0
  10. data/lib/jc-validates_timeliness.rb +1 -0
  11. data/lib/validates_timeliness.rb +70 -0
  12. data/lib/validates_timeliness/attribute_methods.rb +95 -0
  13. data/lib/validates_timeliness/conversion.rb +70 -0
  14. data/lib/validates_timeliness/extensions.rb +14 -0
  15. data/lib/validates_timeliness/extensions/date_time_select.rb +61 -0
  16. data/lib/validates_timeliness/extensions/multiparameter_handler.rb +80 -0
  17. data/lib/validates_timeliness/helper_methods.rb +23 -0
  18. data/lib/validates_timeliness/orm/active_record.rb +53 -0
  19. data/lib/validates_timeliness/orm/mongoid.rb +63 -0
  20. data/lib/validates_timeliness/railtie.rb +15 -0
  21. data/lib/validates_timeliness/validator.rb +117 -0
  22. data/lib/validates_timeliness/version.rb +3 -0
  23. data/spec/spec_helper.rb +109 -0
  24. data/spec/support/config_helper.rb +36 -0
  25. data/spec/support/model_helpers.rb +27 -0
  26. data/spec/support/tag_matcher.rb +35 -0
  27. data/spec/support/test_model.rb +59 -0
  28. data/spec/validates_timeliness/attribute_methods_spec.rb +86 -0
  29. data/spec/validates_timeliness/conversion_spec.rb +234 -0
  30. data/spec/validates_timeliness/extensions/date_time_select_spec.rb +163 -0
  31. data/spec/validates_timeliness/extensions/multiparameter_handler_spec.rb +44 -0
  32. data/spec/validates_timeliness/helper_methods_spec.rb +30 -0
  33. data/spec/validates_timeliness/orm/active_record_spec.rb +244 -0
  34. data/spec/validates_timeliness/orm/mongoid_spec.rb +189 -0
  35. data/spec/validates_timeliness/validator/after_spec.rb +57 -0
  36. data/spec/validates_timeliness/validator/before_spec.rb +57 -0
  37. data/spec/validates_timeliness/validator/is_at_spec.rb +61 -0
  38. data/spec/validates_timeliness/validator/on_or_after_spec.rb +57 -0
  39. data/spec/validates_timeliness/validator/on_or_before_spec.rb +57 -0
  40. data/spec/validates_timeliness/validator_spec.rb +246 -0
  41. data/spec/validates_timeliness_spec.rb +43 -0
  42. data/validates_timeliness.gemspec +25 -0
  43. metadata +157 -0
@@ -0,0 +1,35 @@
1
+ require 'nokogiri'
2
+
3
+ module TagMatcher
4
+ extend RSpec::Matchers::DSL
5
+
6
+ matcher :have_tag do |selector|
7
+ match do |subject|
8
+ matches = doc(subject).search(selector)
9
+
10
+ if @inner_text
11
+ matches = matches.select { |element| element.inner_text == @inner_text }
12
+ end
13
+
14
+ matches.any?
15
+ end
16
+
17
+ chain :with_inner_text do |inner_text|
18
+ @inner_text = inner_text
19
+ end
20
+
21
+ private
22
+
23
+ def body(subject)
24
+ if subject.respond_to?(:body)
25
+ subject.body
26
+ else
27
+ subject.to_s
28
+ end
29
+ end
30
+
31
+ def doc(subject)
32
+ @doc ||= Nokogiri::HTML(body(subject))
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,59 @@
1
+ module TestModel
2
+ extend ActiveSupport::Concern
3
+ extend ActiveModel::Translation
4
+ include ActiveModel::Validations
5
+ include ActiveModel::AttributeMethods
6
+
7
+ included do
8
+ attribute_method_suffix "="
9
+ cattr_accessor :model_attributes
10
+ end
11
+
12
+ module ClassMethods
13
+ def attribute(name, type)
14
+ self.model_attributes ||= {}
15
+ self.model_attributes[name] = type
16
+ end
17
+
18
+ def define_method_attribute=(attr_name)
19
+ generated_attribute_methods.module_eval("def #{attr_name}=(new_value); @attributes['#{attr_name}']=self.class.type_cast('#{attr_name}', new_value); end", __FILE__, __LINE__)
20
+ end
21
+
22
+ def define_method_attribute(attr_name)
23
+ generated_attribute_methods.module_eval("def #{attr_name}; @attributes['#{attr_name}']; end", __FILE__, __LINE__)
24
+ end
25
+
26
+ def type_cast(attr_name, value)
27
+ return value unless value.is_a?(String)
28
+ value.send("to_#{model_attributes[attr_name.to_sym]}") rescue nil
29
+ end
30
+ end
31
+
32
+ def initialize(attributes = nil)
33
+ @attributes = self.class.model_attributes.keys.inject({}) do |hash, column|
34
+ hash[column.to_s] = nil
35
+ hash
36
+ end
37
+ self.attributes = attributes unless attributes.nil?
38
+ end
39
+
40
+ def attributes
41
+ @attributes
42
+ end
43
+
44
+ def attributes=(new_attributes={})
45
+ new_attributes.each do |key, value|
46
+ send "#{key}=", value
47
+ end
48
+ end
49
+
50
+ def method_missing(method_id, *args, &block)
51
+ if match_attribute_method?(method_id.to_s)
52
+ self.class.define_attribute_methods self.class.model_attributes.keys
53
+ send(method_id, *args, &block)
54
+ else
55
+ super
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidatesTimeliness::AttributeMethods do
4
+ it 'should define _timeliness_raw_value_for instance method' do
5
+ expect(PersonWithShim.new).to respond_to(:_timeliness_raw_value_for)
6
+ end
7
+
8
+ describe ".timeliness_validated_attributes" do
9
+ it 'should return attributes validated with plugin validator' do
10
+ PersonWithShim.timeliness_validated_attributes = []
11
+ PersonWithShim.validates_date :birth_date
12
+ PersonWithShim.validates_time :birth_time
13
+ PersonWithShim.validates_datetime :birth_datetime
14
+
15
+ expect(PersonWithShim.timeliness_validated_attributes).to eq([ :birth_date, :birth_time, :birth_datetime ])
16
+ end
17
+ end
18
+
19
+ context "attribute write method" do
20
+ class PersonWithCache
21
+ include TestModel
22
+ include TestModelShim
23
+ attribute :birth_date, :date
24
+ attribute :birth_time, :time
25
+ attribute :birth_datetime, :datetime
26
+ validates_date :birth_date
27
+ validates_time :birth_time
28
+ validates_datetime :birth_datetime
29
+ end
30
+
31
+ it 'should cache attribute raw value' do
32
+ r = PersonWithCache.new
33
+ r.birth_datetime = date_string = '2010-01-01'
34
+ expect(r._timeliness_raw_value_for('birth_datetime')).to eq(date_string)
35
+ end
36
+
37
+ it 'should not overwrite user defined methods' do
38
+ e = Employee.new
39
+ e.birth_date = '2010-01-01'
40
+ expect(e.redefined_birth_date_called).to be_truthy
41
+ end
42
+
43
+ it 'should be undefined if model class has dynamic attribute methods reset' do
44
+ # Force method definitions
45
+ PersonWithShim.validates_date :birth_date
46
+ r = PersonWithShim.new
47
+ r.birth_date = Time.now
48
+
49
+ write_method = RUBY_VERSION < '1.9' ? 'birth_date=' : :birth_date=
50
+
51
+ expect(PersonWithShim.send(:generated_timeliness_methods).instance_methods).to include(write_method)
52
+
53
+ PersonWithShim.undefine_attribute_methods
54
+
55
+ expect(PersonWithShim.send(:generated_timeliness_methods).instance_methods).not_to include(write_method)
56
+ end
57
+
58
+ context "with plugin parser" do
59
+ with_config(:use_plugin_parser, true)
60
+
61
+ class PersonWithParser
62
+ include TestModel
63
+ include TestModelShim
64
+ attribute :birth_date, :date
65
+ attribute :birth_time, :time
66
+ attribute :birth_datetime, :datetime
67
+ validates_date :birth_date
68
+ validates_time :birth_time
69
+ validates_datetime :birth_datetime
70
+ end
71
+
72
+ it 'should parse a string value' do
73
+ expect(Timeliness::Parser).to receive(:parse)
74
+ r = PersonWithParser.new
75
+ r.birth_date = '2010-01-01'
76
+ end
77
+
78
+ end
79
+ end
80
+
81
+ context "before_type_cast method" do
82
+ it 'should not be defined if ORM does not support it' do
83
+ expect(PersonWithShim.new).not_to respond_to(:birth_datetime_before_type_cast)
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,234 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidatesTimeliness::Conversion do
4
+ include ValidatesTimeliness::Conversion
5
+
6
+ let(:options) { Hash.new }
7
+
8
+ before do
9
+ Timecop.freeze(Time.mktime(2010, 1, 1, 0, 0, 0))
10
+ end
11
+
12
+ describe "#type_cast_value" do
13
+ describe "for date type" do
14
+ it "should return same value for date value" do
15
+ expect(type_cast_value(Date.new(2010, 1, 1), :date)).to eq(Date.new(2010, 1, 1))
16
+ end
17
+
18
+ it "should return date part of time value" do
19
+ expect(type_cast_value(Time.mktime(2010, 1, 1, 0, 0, 0), :date)).to eq(Date.new(2010, 1, 1))
20
+ end
21
+
22
+ it "should return date part of datetime value" do
23
+ expect(type_cast_value(DateTime.new(2010, 1, 1, 0, 0, 0), :date)).to eq(Date.new(2010, 1, 1))
24
+ end
25
+
26
+ it 'should return nil for invalid value types' do
27
+ expect(type_cast_value(12, :date)).to eq(nil)
28
+ end
29
+ end
30
+
31
+ describe "for time type" do
32
+ it "should return same value for time value matching dummy date part" do
33
+ expect(type_cast_value(Time.utc(2000, 1, 1, 0, 0, 0), :time)).to eq(Time.utc(2000, 1, 1, 0, 0, 0))
34
+ end
35
+
36
+ it "should return dummy time value with same time part for time value with different date" do
37
+ expect(type_cast_value(Time.utc(2010, 1, 1, 0, 0, 0), :time)).to eq(Time.utc(2000, 1, 1, 0, 0, 0))
38
+ end
39
+
40
+ it "should return dummy time only for date value" do
41
+ expect(type_cast_value(Date.new(2010, 1, 1), :time)).to eq(Time.utc(2000, 1, 1, 0, 0, 0))
42
+ end
43
+
44
+ it "should return dummy date with time part for datetime value" do
45
+ expect(type_cast_value(DateTime.civil_from_format(:utc, 2010, 1, 1, 12, 34, 56), :time)).to eq(Time.utc(2000, 1, 1, 12, 34, 56))
46
+ end
47
+
48
+ it 'should return nil for invalid value types' do
49
+ expect(type_cast_value(12, :time)).to eq(nil)
50
+ end
51
+ end
52
+
53
+ describe "for datetime type" do
54
+ it "should return Date as Time value" do
55
+ expect(type_cast_value(Date.new(2010, 1, 1), :datetime)).to eq(Time.local_time(2010, 1, 1, 0, 0, 0))
56
+ end
57
+
58
+ it "should return same Time value" do
59
+ value = Time.utc(2010, 1, 1, 12, 34, 56)
60
+ expect(type_cast_value(Time.utc(2010, 1, 1, 12, 34, 56), :datetime)).to eq(value)
61
+ end
62
+
63
+ it "should return as Time with same component values" do
64
+ expect(type_cast_value(DateTime.civil_from_format(:utc, 2010, 1, 1, 12, 34, 56), :datetime)).to eq(Time.utc(2010, 1, 1, 12, 34, 56))
65
+ end
66
+
67
+ it "should return same Time in correct zone if timezone aware" do
68
+ @timezone_aware = true
69
+ value = Time.utc(2010, 1, 1, 12, 34, 56)
70
+ result = type_cast_value(value, :datetime)
71
+ expect(result).to eq(Time.zone.local(2010, 1, 1, 23, 34, 56))
72
+ expect(result.zone).to eq('AEDT') # 'Australia/Melbourne'
73
+ end
74
+
75
+ it 'should return nil for invalid value types' do
76
+ expect(type_cast_value(12, :datetime)).to eq(nil)
77
+ end
78
+ end
79
+
80
+ describe "ignore_usec option" do
81
+ let(:options) { {:ignore_usec => true} }
82
+
83
+ it "should ignore usec on time values when evaluated" do
84
+ value = Time.utc(2010, 1, 1, 12, 34, 56, 10000)
85
+ expect(type_cast_value(value, :datetime)).to eq(Time.utc(2010, 1, 1, 12, 34, 56))
86
+ end
87
+
88
+ it "should ignore usec and return time in correct zone if timezone aware" do
89
+ @timezone_aware = true
90
+ value = Time.utc(2010, 1, 1, 12, 34, 56, 10000)
91
+ result = type_cast_value(value, :datetime)
92
+ expect(result).to eq(Time.zone.local(2010, 1, 1, 23, 34, 56))
93
+ expect(result.zone).to eq('AEDT') # 'Australia/Melbourne'
94
+ end
95
+ end
96
+ end
97
+
98
+ describe "#dummy_time" do
99
+ it 'should return Time with dummy date values but same time components' do
100
+ expect(dummy_time(Time.utc(2010, 11, 22, 12, 34, 56))).to eq(Time.utc(2000, 1, 1, 12, 34, 56))
101
+ end
102
+
103
+ it 'should return same value for Time which already has dummy date values' do
104
+ expect(dummy_time(Time.utc(2000, 1, 1, 12, 34, 56))).to eq(Time.utc(2000, 1, 1, 12, 34, 56))
105
+ end
106
+
107
+ it 'should return time component values shifted to current zone if timezone aware' do
108
+ @timezone_aware = true
109
+ expect(dummy_time(Time.utc(2000, 1, 1, 12, 34, 56))).to eq(Time.zone.local(2000, 1, 1, 23, 34, 56))
110
+ end
111
+
112
+ it 'should return base dummy time value for Date value' do
113
+ expect(dummy_time(Date.new(2010, 11, 22))).to eq(Time.utc(2000, 1, 1, 0, 0, 0))
114
+ end
115
+
116
+ describe "with custom dummy date" do
117
+ it 'should return dummy time with custom dummy date' do
118
+ with_config(:dummy_date_for_time_type, [2010, 1, 1] ) do
119
+ expect(dummy_time(Time.utc(1999, 11, 22, 12, 34, 56))).to eq(Time.utc(2010, 1, 1, 12, 34, 56))
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ describe "#evaluate_option_value" do
126
+ let(:person) { Person.new }
127
+
128
+ it 'should return Date object as is' do
129
+ value = Date.new(2010,1,1)
130
+ expect(evaluate_option_value(value, person)).to eq(value)
131
+ end
132
+
133
+ it 'should return Time object as is' do
134
+ value = Time.mktime(2010,1,1)
135
+ expect(evaluate_option_value(value, person)).to eq(value)
136
+ end
137
+
138
+ it 'should return DateTime object as is' do
139
+ value = DateTime.new(2010,1,1,0,0,0)
140
+ expect(evaluate_option_value(value, person)).to eq(value)
141
+ end
142
+
143
+ it 'should return Time value returned from proc with 0 arity' do
144
+ value = Time.mktime(2010,1,1)
145
+ expect(evaluate_option_value(lambda { value }, person)).to eq(value)
146
+ end
147
+
148
+ it 'should return Time value returned by record attribute call in proc arity of 1' do
149
+ value = Time.mktime(2010,1,1)
150
+ person.birth_time = value
151
+ expect(evaluate_option_value(lambda {|r| r.birth_time }, person)).to eq(value)
152
+ end
153
+
154
+ it 'should return Time value for attribute method symbol which returns Time' do
155
+ value = Time.mktime(2010,1,1)
156
+ person.birth_time = value
157
+ expect(evaluate_option_value(:birth_time, person)).to eq(value)
158
+ end
159
+
160
+ it 'should return Time value is default zone from string time value' do
161
+ value = '2010-01-01 12:00:00'
162
+ expect(evaluate_option_value(value, person)).to eq(Time.utc(2010,1,1,12,0,0))
163
+ end
164
+
165
+ it 'should return Time value is current zone from string time value if timezone aware' do
166
+ @timezone_aware = true
167
+ value = '2010-01-01 12:00:00'
168
+ expect(evaluate_option_value(value, person)).to eq(Time.zone.local(2010,1,1,12,0,0))
169
+ end
170
+
171
+ it 'should return Time value in default zone from proc which returns string time' do
172
+ value = '2010-01-01 12:00:00'
173
+ expect(evaluate_option_value(lambda { value }, person)).to eq(Time.utc(2010,1,1,12,0,0))
174
+ end
175
+
176
+ it 'should return Time value for attribute method symbol which returns string time value' do
177
+ value = '2010-01-01 12:00:00'
178
+ person.birth_time = value
179
+ expect(evaluate_option_value(:birth_time, person)).to eq(Time.utc(2010,1,1,12,0,0))
180
+ end
181
+
182
+ context "restriction shorthand" do
183
+ before do
184
+ Timecop.freeze(Time.mktime(2010, 1, 1, 0, 0, 0))
185
+ end
186
+
187
+ it 'should evaluate :now as current time' do
188
+ expect(evaluate_option_value(:now, person)).to eq(Time.now)
189
+ end
190
+
191
+ it 'should evaluate :today as current time' do
192
+ expect(evaluate_option_value(:today, person)).to eq(Date.today)
193
+ end
194
+
195
+ it 'should not use shorthand if symbol if is record method' do
196
+ time = 1.day.from_now
197
+ allow(person).to receive(:now).and_return(time)
198
+ expect(evaluate_option_value(:now, person)).to eq(time)
199
+ end
200
+ end
201
+ end
202
+
203
+ describe "#parse" do
204
+ context "use_plugin_parser setting is true" do
205
+ with_config(:use_plugin_parser, true)
206
+
207
+ it 'should use timeliness' do
208
+ expect(Timeliness::Parser).to receive(:parse)
209
+ parse('2000-01-01')
210
+ end
211
+ end
212
+
213
+ context "use_plugin_parser setting is false" do
214
+ with_config(:use_plugin_parser, false)
215
+
216
+ it 'should use Time.zone.parse attribute is timezone aware' do
217
+ @timezone_aware = true
218
+ expect(Time.zone).to receive(:parse)
219
+ parse('2000-01-01')
220
+ end
221
+
222
+ it 'should use value#to_time if use_plugin_parser setting is false and attribute is not timezone aware' do
223
+ @timezone_aware = false
224
+ value = '2000-01-01'
225
+ expect(value).to receive(:to_time)
226
+ parse(value)
227
+ end
228
+ end
229
+
230
+ it 'should return nil if value is nil' do
231
+ expect(parse(nil)).to be_nil
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe ValidatesTimeliness::Extensions::DateTimeSelect do
4
+ include ActionView::Helpers::DateHelper
5
+ attr_reader :person, :params
6
+
7
+ with_config(:use_plugin_parser, true)
8
+
9
+ before do
10
+ @person = Person.new
11
+ @params = {}
12
+ end
13
+
14
+ describe "datetime_select" do
15
+ it "should use param values when attribute is nil" do
16
+ @params["person"] = {
17
+ "birth_datetime(1i)" => '2009',
18
+ "birth_datetime(2i)" => '2',
19
+ "birth_datetime(3i)" => '29',
20
+ "birth_datetime(4i)" => '12',
21
+ "birth_datetime(5i)" => '13',
22
+ "birth_datetime(6i)" => '14',
23
+ }
24
+ person.birth_datetime = nil
25
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
26
+ should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'February', :day => 29, :hour => 12, :min => 13, :sec => 14)
27
+ end
28
+
29
+ it "should override object values and use params if present" do
30
+ @params["person"] = {
31
+ "birth_datetime(1i)" => '2009',
32
+ "birth_datetime(2i)" => '2',
33
+ "birth_datetime(3i)" => '29',
34
+ "birth_datetime(4i)" => '12',
35
+ "birth_datetime(5i)" => '13',
36
+ "birth_datetime(6i)" => '14',
37
+ }
38
+ person.birth_datetime = "2010-01-01 15:16:17"
39
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
40
+ should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'February', :day => 29, :hour => 12, :min => 13, :sec => 14)
41
+ end
42
+
43
+ it "should use attribute values from object if no params" do
44
+ person.birth_datetime = "2009-01-02 12:13:14"
45
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
46
+ should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'January', :day => 2, :hour => 12, :min => 13, :sec => 14)
47
+ end
48
+
49
+ it "should use attribute values if params does not contain attribute params" do
50
+ person.birth_datetime = "2009-01-02 12:13:14"
51
+ @params["person"] = { }
52
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
53
+ should_have_datetime_selected(:birth_datetime, :year => 2009, :month => 'January', :day => 2, :hour => 12, :min => 13, :sec => 14)
54
+ end
55
+
56
+ it "should not select values when attribute value is nil and has no param values" do
57
+ person.birth_datetime = nil
58
+ @output = datetime_select(:person, :birth_datetime, :include_blank => true, :include_seconds => true)
59
+ should_not_have_datetime_selected(:birth_datetime, :year, :month, :day, :hour, :min, :sec)
60
+ end
61
+ end
62
+
63
+ describe "date_select" do
64
+ it "should use param values when attribute is nil" do
65
+ @params["person"] = {
66
+ "birth_date(1i)" => '2009',
67
+ "birth_date(2i)" => '2',
68
+ "birth_date(3i)" => '29',
69
+ }
70
+ person.birth_date = nil
71
+ @output = date_select(:person, :birth_date, :include_blank => true)
72
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February', :day => 29)
73
+ end
74
+
75
+ it "should override object values and use params if present" do
76
+ @params["person"] = {
77
+ "birth_date(1i)" => '2009',
78
+ "birth_date(2i)" => '2',
79
+ "birth_date(3i)" => '29',
80
+ }
81
+ person.birth_date = "2009-03-01"
82
+ @output = date_select(:person, :birth_date, :include_blank => true)
83
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February', :day => 29)
84
+ end
85
+
86
+ it "should select attribute values from object if no params" do
87
+ person.birth_date = "2009-01-02"
88
+ @output = date_select(:person, :birth_date, :include_blank => true)
89
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'January', :day => 2)
90
+ end
91
+
92
+ it "should select attribute values if params does not contain attribute params" do
93
+ person.birth_date = "2009-01-02"
94
+ @params["person"] = { }
95
+ @output = date_select(:person, :birth_date, :include_blank => true)
96
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'January', :day => 2)
97
+ end
98
+
99
+ it "should not select values when attribute value is nil and has no param values" do
100
+ person.birth_date = nil
101
+ @output = date_select(:person, :birth_date, :include_blank => true)
102
+ should_not_have_datetime_selected(:birth_time, :year, :month, :day)
103
+ end
104
+
105
+ it "should allow the day part to be discarded" do
106
+ @params["person"] = {
107
+ "birth_date(1i)" => '2009',
108
+ "birth_date(2i)" => '2',
109
+ }
110
+
111
+ @output = date_select(:person, :birth_date, :include_blank => true, :discard_day => true)
112
+ should_have_datetime_selected(:birth_date, :year => 2009, :month => 'February')
113
+ should_not_have_datetime_selected(:birth_time, :day)
114
+ expect(@output).to have_tag("input[id=person_birth_date_3i][type=hidden][value='1']")
115
+ end
116
+ end
117
+
118
+ describe "time_select" do
119
+ before do
120
+ Timecop.freeze Time.mktime(2009,1,1)
121
+ end
122
+
123
+ it "should use param values when attribute is nil" do
124
+ @params["person"] = {
125
+ "birth_time(1i)" => '2000',
126
+ "birth_time(2i)" => '1',
127
+ "birth_time(3i)" => '1',
128
+ "birth_time(4i)" => '12',
129
+ "birth_time(5i)" => '13',
130
+ "birth_time(6i)" => '14',
131
+ }
132
+ person.birth_time = nil
133
+ @output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
134
+ should_have_datetime_selected(:birth_time, :hour => 12, :min => 13, :sec => 14)
135
+ end
136
+
137
+ it "should select attribute values from object if no params" do
138
+ person.birth_time = "2000-01-01 12:13:14"
139
+ @output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
140
+ should_have_datetime_selected(:birth_time, :hour => 12, :min => 13, :sec => 14)
141
+ end
142
+
143
+ it "should not select values when attribute value is nil and has no param values" do
144
+ person.birth_time = nil
145
+ @output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true)
146
+ should_not_have_datetime_selected(:birth_time, :hour, :min, :sec)
147
+ end
148
+ end
149
+
150
+ def should_have_datetime_selected(field, datetime_hash)
151
+ datetime_hash.each do |key, value|
152
+ index = {:year => 1, :month => 2, :day => 3, :hour => 4, :min => 5, :sec => 6}[key]
153
+ expect(@output).to have_tag("select[id=person_#{field}_#{index}i] option[selected=selected]").with_inner_text(value.to_s)
154
+ end
155
+ end
156
+
157
+ def should_not_have_datetime_selected(field, *attributes)
158
+ attributes.each do |attribute|
159
+ index = {:year => 1, :month => 2, :day => 3, :hour => 4, :min => 5, :sec => 6}[attribute]
160
+ expect(@output).not_to have_tag("select[id=person_#{attribute}_#{index}i] option[selected=selected]")
161
+ end
162
+ end
163
+ end