semanticgap_date_time_form 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
@@ -0,0 +1,36 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "semanticgap_date_time_form"
3
+ s.version = "0.1"
4
+
5
+ s.authors = ["SemanticGap"]
6
+ s.date = "2010-05-08"
7
+ s.description = "An improved date time selector for Rails."
8
+ s.email = "info@semanticgap.com"
9
+ s.add_dependency "nayutaya-active-form"
10
+ s.files = [ "./lib/semanticgap_date_time_form/active_record_mixin.rb",
11
+ "./lib/semanticgap_date_time_form/form.rb",
12
+ "./lib/semanticgap_date_time_form/form_builder_mixin.rb",
13
+ "./lib/semanticgap_date_time_form/spec.rb",
14
+ "./lib/semanticgap_date_time_form.rb",
15
+ "./MIT-LICENSE",
16
+ "./public/stylesheets/semanticgap_date_time_form.css",
17
+ "./rails/init.rb",
18
+ "./rails/install.rb",
19
+ "./rails/uninstall.rb",
20
+ "./Rakefile",
21
+ "./README",
22
+ "./semanticgap_date_time_form.gemspec",
23
+ "./semanticgap_date_time_form.gemspec~",
24
+ "./spec/application.rb",
25
+ "./spec/integration/post_spec.rb",
26
+ "./spec/spec_helper.rb",
27
+ "./spec/unit/active_record_mixin_spec.rb",
28
+ "./spec/unit/form_builder_mixin_spec.rb",
29
+ "./spec/unit/form_spec.rb",
30
+ "./tasks/semanticgap_datetime_fields_tasks.rake" ]
31
+ s.homepage = "http://git.oss.semanticgap.com/ruby/semanticgap_date_time_form.git
32
+ "
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.5}
35
+ s.summary = "Improved date time selector"
36
+ end
@@ -0,0 +1,39 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "refinerycms-events"
3
+ s.version = "0.0.1"
4
+
5
+ s.authors = ["SemanticGap"]
6
+ s.date = "2010-05-07"
7
+ s.default_executable = "refinerycms-events-install"
8
+ s.description = "A really straightforward open source Ruby on Rails events plugin designed for integration with RefineryCMS."
9
+ s.email = "info@semanticgap.com"
10
+ s.add_dependency "nayutaya-active-form"
11
+ s.add_dependency "elevation_event_calendar"
12
+ s.executables = ["refinerycms-events-install"]
13
+ s.files = [ "db/migrate/20100430163757_create_events.rb",
14
+ "db/migrate/20100501234548_add_color_to_events.rb",
15
+ "db/migrate/20100502004451_add_all_day_to_events.rb",
16
+ "app/models/calendar.rb",
17
+ "app/models/event.rb",
18
+ "app/controllers/events_controller.rb",
19
+ "app/controllers/admin/events_controller.rb",
20
+ "app/helpers/calendars_helper.rb",
21
+ "app/views/events/index.html.erb",
22
+ "app/views/events/show.html.erb",
23
+ "app/views/events/_event_list.html.erb",
24
+ "app/views/admin/events/_event.html.erb",
25
+ "app/views/admin/events/_form.html.erb",
26
+ "app/views/admin/events/_sortable_list.html.erb",
27
+ "app/views/admin/events/edit.html.erb",
28
+ "app/views/admin/events/index.html.erb",
29
+ "app/views/admin/events/new.html.erb",
30
+ "config/routes.rb",
31
+ "public/stylesheets/event_calendar.css",
32
+ "public/javascripts/event_calendar.js",
33
+ "rails/init.rb",
34
+ "bin/refinerycms-events-install" ]
35
+ s.homepage = "http://github.com/semanticgap/refinerycms-events"
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.5}
38
+ s.summary = "Ruby on Rails events plugin for RefineryCMS."
39
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,36 @@
1
+ require File.join(File.dirname(__FILE__), '../spec_helper')
2
+ require 'semanticgap_date_time_form/spec'
3
+
4
+ class Post < ActiveRecord::Base
5
+ class Migration < ActiveRecord::Migration
6
+ def self.up
7
+ create_table :posts do |t|
8
+ t.datetime :published_at
9
+ t.datetime :created_at
10
+ end
11
+ end
12
+ end
13
+
14
+ datetime_fields_for :created_at
15
+ datetime_fields_for :published_at, :allow_blank => true
16
+ end
17
+
18
+ describe Post do
19
+ include SemanticGap::DateTimeForm::Spec
20
+
21
+ before(:all) do
22
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => 'test.sqlite3')
23
+ Post::Migration.up
24
+ end
25
+
26
+ after(:all) do
27
+ FileUtils.rm('test.sqlite3')
28
+ end
29
+
30
+ before(:each) do
31
+ subject.created_at = DateTime.now
32
+ end
33
+
34
+ it_has_datetime_fields_for :published_at, :allow_blank => true
35
+ it_has_datetime_fields_for :created_at
36
+ end
@@ -0,0 +1,18 @@
1
+ RAILS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
2
+ module Rails
3
+ module VERSION
4
+ STRING = '0.0.1'
5
+ end
6
+ end
7
+
8
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'vendor', 'active_form', 'lib'))
9
+
10
+ require 'rubygems'
11
+ require 'active_record'
12
+ require 'active_form'
13
+ require 'action_controller'
14
+ require 'action_view'
15
+ require 'semanticgap_date_time_form'
16
+
17
+ require 'spec'
18
+ require 'spec/rails'
@@ -0,0 +1,41 @@
1
+ require File.join(File.dirname(__FILE__), '../spec_helper')
2
+
3
+ describe SemanticGap::DateTimeForm::ActiveRecordMixin::ClassMethods do
4
+ describe '#datetime_fields_for' do
5
+ before(:each) do
6
+ @klass = Class.new do
7
+ def self.validate(meth); end
8
+ def self.before_save(meth); end
9
+
10
+ include SemanticGap::DateTimeForm::ActiveRecordMixin
11
+ datetime_fields_for :published_at
12
+ end
13
+ end
14
+
15
+ subject { @klass.new }
16
+
17
+ context 'for a field named "published_at"' do
18
+ it "defines 'published_at_fields'" do
19
+ subject.should respond_to(:published_at_fields)
20
+ end
21
+
22
+ it "defines 'publihsed_at_fields='" do
23
+ subject.should respond_to(:published_at_fields=)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ describe SemanticGap::DateTimeForm::ActiveRecordMixin do
30
+ it "is included into ActiveRecord::Base" do
31
+ ActiveRecord::Base.should include(SemanticGap::DateTimeForm::ActiveRecordMixin)
32
+ end
33
+
34
+ describe '.included' do
35
+ it "adds #datetime_fields_for to the class" do
36
+ klass = Class.new
37
+ klass.send(:include, SemanticGap::DateTimeForm::ActiveRecordMixin)
38
+ klass.should respond_to(:datetime_fields_for)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,98 @@
1
+ require File.join(File.dirname(__FILE__), '../spec_helper')
2
+
3
+ describe SemanticGap::DateTimeForm::FormBuilderMixin do
4
+ include ActionController::Assertions::SelectorAssertions
5
+
6
+ def build_view
7
+ v = ActionView::Base.new
8
+ v.send(:extend, ActionView::Helpers::FormHelper)
9
+ v.send(:extend, ActionView::Helpers::DateHelper)
10
+ v.send(:extend, ActionView::Helpers::FormOptionsHelper)
11
+ v.send(:extend, ActionView::Helpers::TagHelper)
12
+ v
13
+ end
14
+
15
+ before(:each) do
16
+ @fields = SemanticGap::DateTimeForm::Form.new(:time_zone => ActiveSupport::TimeZone.new('Eastern Time (US & Canada)'))
17
+ @object = mock('object', :published_at_fields => @fields)
18
+ @template = build_view
19
+ @options = { }
20
+ end
21
+
22
+ subject { ActionView::Helpers::FormBuilder.new('object', @object, @template, @options, nil) }
23
+
24
+ it "is included into ActionView::Helpers::FormBuilder" do
25
+ ActionView::Helpers::FormBuilder.should include(SemanticGap::DateTimeForm::FormBuilderMixin)
26
+ end
27
+
28
+ describe '#datetime_form' do
29
+ TagArgs = {
30
+ :year => [ 'input[type=?][size=?][name=?]', 'text', '4', 'object[published_at_fields][year]' ],
31
+ :month => [ 'select[name=?]', 'object[published_at_fields][month]' ],
32
+ :day => [ 'input[type=?][size=?][name=?]', 'text', '2', 'object[published_at_fields][day]' ],
33
+ :hour => [ 'input[type=?][size=?][name=?]', 'text', '2', 'object[published_at_fields][hour]' ],
34
+ :minute => [ 'input[type=?][size=?][name=?]', 'text', '2', 'object[published_at_fields][minute]' ],
35
+ :ampm => [ 'select[name=?]', 'object[published_at_fields][ampm]' ],
36
+ :time_zone => [ 'span[class=?]', 'timezone', 'Eastern Time (US & Canada)' ]
37
+ }
38
+
39
+ context 'basic datetime form' do
40
+ before(:each) do
41
+ @result = subject.datetime_form(:published_at)
42
+ end
43
+
44
+ it "returns a div with class 'sg-datetime-form'" do
45
+ @result.should have_tag('div', :class => 'sg-datetime-form') do
46
+ with_tag(*TagArgs[:year])
47
+ with_tag(*TagArgs[:month])
48
+ with_tag(*TagArgs[:day])
49
+ with_tag(*TagArgs[:hour])
50
+ with_tag(*TagArgs[:minute])
51
+ with_tag(*TagArgs[:ampm])
52
+ with_tag(*TagArgs[:time_zone])
53
+ end
54
+ end
55
+
56
+ it "has a text field for the year" do
57
+ @result.should have_tag(*TagArgs[:year])
58
+ end
59
+
60
+ it "has a select field for the month" do
61
+ @result.should have_tag(*TagArgs[:month])
62
+ end
63
+
64
+ it "has a text field for the day" do
65
+ @result.should have_tag(*TagArgs[:day])
66
+ end
67
+
68
+ it "has a text field for the hour" do
69
+ @result.should have_tag(*TagArgs[:hour])
70
+ end
71
+
72
+ it "has a text field for the minute" do
73
+ @result.should have_tag(*TagArgs[:minute])
74
+ end
75
+
76
+ it "has a select field for ampm" do
77
+ @result.should have_tag(*TagArgs[:ampm])
78
+ end
79
+
80
+ it "has shows the time zone" do
81
+ @result.should have_tag(*TagArgs[:time_zone])
82
+ end
83
+ end
84
+
85
+ context 'when the fields allow blank' do
86
+ before(:each) do
87
+ @fields.stub!(:allow_blank?).and_return(true)
88
+ @result = subject.datetime_form(:published_at)
89
+ end
90
+
91
+ it "includes a blank option in the month select field" do
92
+ @result.should have_tag(*TagArgs[:month]) do
93
+ with_tag('option[value=?]', '')
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,583 @@
1
+ require File.join(File.dirname(__FILE__), '../spec_helper')
2
+
3
+ describe SemanticGap::DateTimeForm::Form do
4
+ def self.it_has_the_attributes(*attrs)
5
+ attrs.each do |attr|
6
+ describe "\##{attr}" do
7
+ it "is an accessor for @#{attr}" do
8
+ subject.send(:instance_variable_set, "@#{attr}", :hello)
9
+ subject.send(attr).should == :hello
10
+ end
11
+ end
12
+
13
+ describe "\##{attr}=" do
14
+ it "changes @#{attr}" do
15
+ lambda { subject.send("#{attr}=", :hello) }.
16
+ should change { subject.send(:instance_variable_get, "@#{attr}") }.
17
+ to(:hello)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ Attributes = [ :year, :month, :day, :hour, :minute, :ampm ]
24
+
25
+ it "is an active form" do
26
+ subject.should be_kind_of(ActiveForm)
27
+ end
28
+
29
+ it_has_the_attributes :year, :month, :day
30
+ it_has_the_attributes :hour, :minute, :ampm
31
+ it_has_the_attributes :time_zone
32
+
33
+ describe '#initialize' do
34
+ context 'no arguments' do
35
+ subject { described_class.new }
36
+
37
+ context 'when Time.zone is set' do
38
+ before(:each) do
39
+ @old_zone = Time.zone
40
+ Time.zone = ActiveSupport::TimeZone.new('Eastern Time (US & Canada)')
41
+ Time.zone.should_not be_nil
42
+ end
43
+
44
+ after(:each) do
45
+ Time.zone = @old_zone
46
+ end
47
+
48
+ it "sets the time zone to Time.zone" do
49
+ subject.time_zone.should == Time.zone
50
+ end
51
+ end
52
+
53
+ context 'when Time.zone is unset' do
54
+ before(:each) do
55
+ @old_zone = Time.zone
56
+ Time.zone = nil
57
+ end
58
+
59
+ after(:each) do
60
+ Time.zone = @old_zone
61
+ end
62
+
63
+ it "sets the time zone to UTC" do
64
+ subject.time_zone.should == ActiveSupport::TimeZone.new('UTC')
65
+ end
66
+ end
67
+
68
+ it "does NOT allow blanks" do
69
+ subject.should_not be_allow_blank
70
+ end
71
+
72
+ it "is not valid" do
73
+ subject.should_not be_valid
74
+ end
75
+
76
+ it "leaves the attributes blank" do
77
+ Attributes.each do |attr|
78
+ subject.send(attr).should be_nil
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'options hash' do
84
+ context 'with :allow_blank' do
85
+ subject { described_class.new(:allow_blank => true) }
86
+
87
+ it "allows blanks" do
88
+ subject.should be_allow_blank
89
+ end
90
+
91
+ it "is valid" do
92
+ subject.should be_valid
93
+ end
94
+ end
95
+
96
+ context 'with :time_zone' do
97
+ before(:each) do
98
+ @zone = ActiveSupport::TimeZone.new('Eastern (US & Canada)')
99
+ end
100
+
101
+ subject do
102
+ described_class.new(:time_zone => @zone)
103
+ end
104
+
105
+ it "sets the time zone to the supplied value" do
106
+ subject.time_zone.should == @zone
107
+ end
108
+ end
109
+ end
110
+
111
+ context 'with a DateTime' do
112
+ { DateTime.new(2010, 5, 6, 20, 1) => %W(2010 5 6 08 01 PM),
113
+ DateTime.new(2010, 5, 6, 8, 59) => %W(2010 5 6 08 59 AM),
114
+ }.each do |date, (year, month, day, hour, minute, ampm)|
115
+ context "with #{date}" do
116
+ subject { described_class.new(date) }
117
+
118
+ it "sets the attributes to the DateTime's components" do
119
+ subject.year.should == year.to_i
120
+ subject.month.should == month.to_i
121
+ subject.day.should == day.to_i
122
+ subject.hour.should == hour
123
+ subject.minute.should == minute
124
+ subject.ampm.should == ampm
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ context 'with a DateTime and options Hash' do
131
+ before(:each) do
132
+ @date = DateTime.new(2010, 5, 6, 20, 1)
133
+ @zone = ActiveSupport::TimeZone.new('Eastern Time (US & Canada)')
134
+ end
135
+
136
+ subject { described_class.new(@date, :allow_blank => true, :time_zone => @zone) }
137
+
138
+ it "sets the date to the DateTime" do
139
+ subject.to_datetime.should == @date
140
+ end
141
+
142
+ it "sets the options" do
143
+ subject.should be_allow_blank
144
+ subject.time_zone.should == @zone
145
+ end
146
+ end
147
+ end
148
+
149
+ describe 'validations' do
150
+ describe 'when blanks are allowed' do
151
+ subject { described_class.new(:allow_blank => true) }
152
+
153
+ it "is valid when all attributes are blank" do
154
+ subject.should be_valid
155
+ end
156
+
157
+ it "is valid when all attributes are blank except ampm" do
158
+ subject.ampm = 'AM'
159
+ subject.should be_valid
160
+ end
161
+
162
+ [ :year, :month, :day, :hour, :minute ].each do |attr|
163
+ it "is invalid if #{attr} has a value" do
164
+ subject.send("#{attr}=", 1)
165
+ subject.should_not be_valid
166
+ end
167
+ end
168
+ end
169
+
170
+ describe 'on year' do
171
+ { 1 => true,
172
+ 2010 => true,
173
+ 0 => true,
174
+ 14 => true,
175
+ -1 => true,
176
+ '-10' => true,
177
+ '-1' => true,
178
+ 'A' => false,
179
+ 'abcd' => false,
180
+ '' => false,
181
+ ' ' => false
182
+ }.each do |value, valid|
183
+ it "is #{valid ? 'valid' : 'invalid'} for #{value}" do
184
+ subject.year = value
185
+
186
+ if valid
187
+ subject.should_not have(:any).errors_on(:year)
188
+ else
189
+ subject.should have_at_least(1).error_on(:year)
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ describe 'on month' do
196
+ it "must be between 1 and 12" do
197
+ (1..12).each do |i|
198
+ subject.month = i
199
+ subject.should_not have(:any).errors_on(:month)
200
+ end
201
+ end
202
+
203
+ { 1 => true,
204
+ 12 => true,
205
+ '10' => true,
206
+ 0 => false,
207
+ 14 => false,
208
+ -1 => false,
209
+ '-10' => false,
210
+ '-1' => false,
211
+ 'A' => false,
212
+ '' => false,
213
+ ' ' => false
214
+ }.each do |value, valid|
215
+ it "is #{valid ? 'valid' : 'invalid'} for #{value}" do
216
+ subject.month = value
217
+
218
+ if valid
219
+ subject.should_not have(:any).errors_on(:month)
220
+ else
221
+ subject.should have_at_least(1).error_on(:month)
222
+ end
223
+ end
224
+ end
225
+ end
226
+
227
+ describe 'on day' do
228
+ context 'with a blank month' do
229
+ before(:each) do
230
+ subject.month = nil
231
+ end
232
+
233
+ it "must be between 1 and 31" do
234
+ (1..31).each do |i|
235
+ subject.day = i
236
+ subject.should_not have(:any).errors_on(:day)
237
+ end
238
+ end
239
+
240
+ { '1' => true,
241
+ '31' => true,
242
+ '10' => true,
243
+ 0 => false,
244
+ 32 => false,
245
+ -1 => false,
246
+ '-10' => false,
247
+ '-1' => false,
248
+ 'A' => false,
249
+ '' => false,
250
+ ' ' => false
251
+ }.each do |value, valid|
252
+ it "is #{valid ? 'valid' : 'invalid'} for #{value}" do
253
+ subject.day = value
254
+
255
+ if valid
256
+ subject.should_not have(:any).errors_on(:day)
257
+ else
258
+ subject.should have_at_least(1).error_on(:day)
259
+ end
260
+ end
261
+ end
262
+ end
263
+
264
+ { 2010 => {
265
+ 1 => 31,
266
+ 2 => 28,
267
+ 3 => 31,
268
+ 4 => 30,
269
+ 5 => 31,
270
+ 6 => 30,
271
+ 7 => 31,
272
+ 8 => 31,
273
+ 9 => 30,
274
+ 10 => 31,
275
+ 11 => 30,
276
+ 12 => 31
277
+ },
278
+ 2008 => {
279
+ 1 => 31,
280
+ 2 => 29,
281
+ 3 => 31,
282
+ 4 => 30,
283
+ 5 => 31,
284
+ 6 => 30,
285
+ 7 => 31,
286
+ 8 => 31,
287
+ 9 => 30,
288
+ 10 => 31,
289
+ 11 => 30,
290
+ 12 => 31
291
+ }
292
+ }.each do |year, months|
293
+ context "in the year #{year}" do
294
+ subject { described_class.new(:allow_blank => true) }
295
+
296
+ before(:each) do
297
+ subject.year = year
298
+ end
299
+
300
+ months.each do |month, num_days|
301
+ context "with month set to #{month}" do
302
+ before(:each) do
303
+ subject.month = month
304
+ end
305
+
306
+ it "is valid when day is set to #{num_days - 1}" do
307
+ subject.day = num_days - 1
308
+ subject.should be_valid
309
+ end
310
+
311
+ it "is valid when day is set to #{num_days}" do
312
+ subject.day = num_days
313
+ subject.should be_valid
314
+ end
315
+
316
+ it "is invalid when day is set to #{num_days + 1}" do
317
+ subject.day = num_days + 1
318
+ subject.should_not be_valid
319
+ subject.should have_at_least(1).error_on(:day)
320
+ end
321
+ end
322
+ end
323
+ end
324
+ end
325
+ end
326
+
327
+ describe 'hour' do
328
+ it "must be between 0 and 23" do
329
+ (0..23).each do |i|
330
+ subject.hour = i
331
+ subject.should_not have(:any).errors_on(:hour)
332
+ end
333
+ end
334
+
335
+ { '0' => true,
336
+ '12' => true,
337
+ 23 => true,
338
+ '10' => true,
339
+ 24 => false,
340
+ 25 => false,
341
+ -1 => false,
342
+ '-10' => false,
343
+ '-1' => false,
344
+ 'A' => false,
345
+ '' => false,
346
+ ' ' => false
347
+ }.each do |value, valid|
348
+ it "is #{valid ? 'valid' : 'invalid'} for #{value.inspect}" do
349
+ subject.hour = value
350
+
351
+ if valid
352
+ subject.should_not have(:any).errors_on(:hour)
353
+ else
354
+ subject.should have_at_least(1).error_on(:hour)
355
+ end
356
+ end
357
+ end
358
+ end
359
+
360
+ describe 'minute' do
361
+ it "must be between 0 and 59" do
362
+ (0..59).each do |i|
363
+ subject.minute = i
364
+ subject.should_not have(:any).errors_on(:minute)
365
+ end
366
+ end
367
+
368
+ { '0' => true,
369
+ '59' => true,
370
+ 59 => true,
371
+ '10' => true,
372
+ 60 => false,
373
+ 61 => false,
374
+ -1 => false,
375
+ '-10' => false,
376
+ '-1' => false,
377
+ 'A' => false,
378
+ '' => false,
379
+ ' ' => false
380
+ }.each do |value, valid|
381
+ it "is #{valid ? 'valid' : 'invalid'} for #{value.inspect}" do
382
+ subject.minute = value
383
+
384
+ if valid
385
+ subject.should_not have(:any).errors_on(:minute)
386
+ else
387
+ subject.should have_at_least(1).error_on(:minute)
388
+ end
389
+ end
390
+ end
391
+ end
392
+
393
+ describe 'ampm' do
394
+ %W(am AM aM Am pm PM pM Pm).each do |value|
395
+ it "is valid with #{value.inspect}" do
396
+ subject.ampm = value
397
+ subject.should_not have(:any).errors_on(:ampm)
398
+ end
399
+ end
400
+
401
+ values = %W(a p A P AB JM Hello hello pay)
402
+ values << "" << " " << " "
403
+ values.each do |value|
404
+ it "is invalid with #{value.inspect}" do
405
+ subject.ampm = value
406
+ subject.should have_at_least(1).errors_on(:ampm)
407
+ end
408
+ end
409
+ end
410
+ end
411
+
412
+ describe '#date=' do
413
+ it "adjusts the date to local time" do
414
+ @utc = DateTime.parse("2010/05/06 16:00 PM UTC")
415
+ @zone = ActiveSupport::TimeZone.new('Eastern Time (US & Canada)')
416
+ subject.time_zone = @zone
417
+
418
+ subject.date = @utc
419
+ subject.hour.should == '12'
420
+ subject.should be_pm
421
+ end
422
+
423
+ { DateTime.new(2010, 5, 6, 20, 1) => %W(2010 5 6 08 01 PM),
424
+ DateTime.new(2010, 5, 6, 8, 59) => %W(2010 5 6 08 59 AM),
425
+ DateTime.new(2010, 5, 6, 12, 1) => %W(2010 5 6 12 01 PM),
426
+ DateTime.new(2010, 5, 6, 0, 59) => %W(2010 5 6 12 59 AM),
427
+ Date.new(2010, 5, 6) => %W(2010 5 6 12 00 AM),
428
+ Time.parse('2010/5/6 0:00 UTC') => %W(2010 5 6 12 00 AM)
429
+ }.each do |date, (year, month, day, hour, minute, ampm)|
430
+ context "with #{date}" do
431
+ before(:each) do
432
+ subject.date = date
433
+ end
434
+
435
+ it "sets year to #{year.to_i.inspect}" do
436
+ subject.year.should == year.to_i
437
+ end
438
+
439
+ it "sets month to #{month.to_i.inspect}" do
440
+ subject.month.should == month.to_i
441
+ end
442
+
443
+ it "sets day to #{day.to_i.inspect}" do
444
+ subject.day.should == day.to_i
445
+ end
446
+
447
+ it "sets hour to #{hour.inspect}" do
448
+ subject.hour.should == hour
449
+ end
450
+
451
+ it "sets minute to #{minute.inspect}" do
452
+ subject.minute.should == minute
453
+ end
454
+
455
+ it "sets ampm to #{ampm.inspect}" do
456
+ subject.ampm.should == ampm
457
+ end
458
+
459
+ it "converts to the supplied date" do
460
+ subject.to_datetime.should == date
461
+ end
462
+ end
463
+ end
464
+ end
465
+
466
+ describe '#time_zone_name' do
467
+ it "returns the time zone's name" do
468
+ subject.time_zone = mock('zone', :name => 'TZ')
469
+ subject.time_zone.name.should == 'TZ'
470
+ end
471
+ end
472
+
473
+ describe '#time_zone_name=' do
474
+ before(:each) do
475
+ @utc = ActiveSupport::TimeZone.new('UTC')
476
+ @eastern = ActiveSupport::TimeZone.new('Eastern Time (US & Canada)')
477
+ ActiveSupport::TimeZone.stub!(:new).and_return(@utc)
478
+ end
479
+
480
+ it "creates a new TimeZone from the value" do
481
+ ActiveSupport::TimeZone.should_receive(:new).
482
+ with('Eastern Time (US & Canada)').
483
+ and_return(@eastern)
484
+
485
+ subject.time_zone_name = 'Eastern Time (US & Canada)'
486
+ end
487
+
488
+ context 'valid time zone' do
489
+ it "changes the time zone" do
490
+ ActiveSupport::TimeZone.should_receive(:new).and_return(@eastern)
491
+
492
+ lambda { subject.time_zone_name = 'Eastern Time (US & Canada)' }.should change(subject, :time_zone)
493
+ end
494
+ end
495
+
496
+ context 'invalid time zone' do
497
+ it "does not change the time zone" do
498
+ lambda { subject.time_zone_name = 'WTF' }.should_not change(subject, :time_zone_name)
499
+ end
500
+ end
501
+ end
502
+
503
+ describe '#to_datetime' do
504
+ context 'when valid' do
505
+ before(:each) do
506
+ @time = DateTime.new(2010, 5, 5, 20, 27)
507
+ end
508
+
509
+ subject { described_class.new(@time) }
510
+
511
+ it "returns a DateTime created from the attributes, but adjusted to the time zone" do
512
+ subject.to_datetime.should == subject.time_zone.utc_to_local(@time)
513
+ end
514
+ end
515
+
516
+ context 'when invalid' do
517
+ before(:each) do
518
+ subject.hour = 25
519
+ end
520
+
521
+ it "returns nil" do
522
+ subject.to_datetime.should be_nil
523
+ end
524
+ end
525
+ end
526
+
527
+ describe '#pm?' do
528
+ %W(am Am AM aM a hello).each do |v|
529
+ context "with #{v.inspect}" do
530
+ before(:each) do
531
+ subject.ampm = v
532
+ end
533
+
534
+ it "is false for #{v.inspect}" do
535
+ subject.should_not be_pm
536
+ end
537
+ end
538
+ end
539
+
540
+ %W(pm Pm PM pM p).each do |v|
541
+ context "with #{v.inspect}" do
542
+ before(:each) do
543
+ subject.ampm = v
544
+ end
545
+
546
+ it "is true for #{v.inspect}" do
547
+ subject.should be_pm
548
+ end
549
+ end
550
+ end
551
+ end
552
+
553
+ describe '#blank?' do
554
+ it "is true if all the attributes are blank" do
555
+ subject.should be_blank
556
+ end
557
+
558
+ [ :year, :month, :day, :hour, :minute ].each do |attr|
559
+ it "is false if #{attr} has a value" do
560
+ subject.send("#{attr}=", 1)
561
+ subject.should_not be_blank
562
+ end
563
+ end
564
+ end
565
+
566
+ describe '#allow_blank?' do
567
+ context 'when :allow_blank was true during creation' do
568
+ subject { described_class.new(:allow_blank => true) }
569
+
570
+ it "is true" do
571
+ subject.should be_allow_blank
572
+ end
573
+ end
574
+
575
+ context 'when :allow_blank was false during creation' do
576
+ subject { described_class.new(:allow_blank => false) }
577
+
578
+ it "is true" do
579
+ subject.should_not be_allow_blank
580
+ end
581
+ end
582
+ end
583
+ end