timecop 0.4.3 → 0.5.0

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/History.rdoc CHANGED
@@ -1,4 +1,29 @@
1
- === 0.4.1 / 2012-07-27
1
+ === 0.5.0 / 2012-09-12
2
+
3
+ * Maintenance
4
+ * Timecop#travel, Timecop#freeze blocks return nil or block value
5
+
6
+ === 0.4.6 / 2012-09-05
7
+
8
+ * Maintenance
9
+ * Fix rounding support for Ruby < 1.9
10
+
11
+ === 0.4.5 / 2012-08-09
12
+
13
+ * Maintenance
14
+ * Subclasses of Time/Date/DateTime now return proper instances
15
+
16
+ === 0.4.4 / 2012-07-29
17
+
18
+ * Maintenance
19
+ * Can now configure Timecop to not use ActiveSupport by setting Timecop.active_support = false
20
+
21
+ === 0.4.3 / 2012-07-27
22
+
23
+ * Maintenance
24
+ * Fix alias of Time#new/Time#now when Time#new given with args
25
+
26
+ === 0.4.2 / 2012-07-27
2
27
 
3
28
  * Maintenance
4
29
  * Mock Time#new the same as Time#now since they're synonyms
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 3
2
+ :patch: 0
3
3
  :major: 0
4
- :minor: 4
4
+ :minor: 5
@@ -4,7 +4,7 @@ class Time #:nodoc:
4
4
  # Time we are behaving as
5
5
  def mock_time
6
6
  mocked_time_stack_item = Timecop.top_stack_item
7
- mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time
7
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time(self)
8
8
  end
9
9
 
10
10
  # Alias the original now
@@ -19,10 +19,12 @@ class Time #:nodoc:
19
19
  alias_method :now, :now_with_mock_time
20
20
 
21
21
  alias_method :new_without_mock_time, :new
22
+
22
23
  def new_with_mock_time *args
23
- if args.size > 0
24
+ begin
25
+ raise ArgumentError.new if args.size <= 0
24
26
  new_without_mock_time *args
25
- else
27
+ rescue ArgumentError
26
28
  now
27
29
  end
28
30
  end
@@ -37,7 +39,7 @@ if Object.const_defined?(:Date) && Date.respond_to?(:today)
37
39
  # Date we are behaving as
38
40
  def mock_date
39
41
  mocked_time_stack_item = Timecop.top_stack_item
40
- mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date
42
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date(self)
41
43
  end
42
44
 
43
45
  # Alias the original today
@@ -60,7 +62,7 @@ if Object.const_defined?(:DateTime) && DateTime.respond_to?(:now)
60
62
  # Time we are behaving as
61
63
  def mock_time
62
64
  mocked_time_stack_item = Timecop.top_stack_item
63
- mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime
65
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime(self)
64
66
  end
65
67
 
66
68
  # Fake alias :now_without_mock_time :now
@@ -45,24 +45,29 @@ class Timecop
45
45
  @travel_offset
46
46
  end
47
47
 
48
- def time #:nodoc:
48
+ def time(time_klass=Time) #:nodoc:
49
49
  if travel_offset.nil?
50
- @time.clone
50
+ time_klass.at( @time.to_f )
51
51
  else
52
- Time.now_without_mock_time + travel_offset
52
+ time_klass.at( ( Time.now_without_mock_time + travel_offset ).to_f )
53
53
  end
54
54
  end
55
55
 
56
- def date
57
- time.send(:to_date)
56
+ def date(date_klass=Date)
57
+ date_klass.jd(time.__send__(:to_date).jd)
58
58
  end
59
59
 
60
- def datetime
60
+ def datetime(datetime_klass=DateTime)
61
61
  # DateTime doesn't know about DST, so let's remove its presence
62
62
  our_offset = utc_offset + dst_adjustment
63
- fractions_of_a_second = time.to_f % 1
64
- DateTime.new(year, month, day, hour, min, sec + fractions_of_a_second,
65
- utc_offset_to_rational(our_offset))
63
+ if Float.method_defined?(:to_r)
64
+ fractions_of_a_second = time.to_f % 1
65
+ datetime_klass.new(year, month, day, hour, min, sec + fractions_of_a_second,
66
+ utc_offset_to_rational(our_offset))
67
+ else
68
+ our_offset = utc_offset + dst_adjustment
69
+ datetime_klass.new(year, month, day, hour, min, sec, utc_offset_to_rational(our_offset))
70
+ end
66
71
  end
67
72
 
68
73
  def dst_adjustment
@@ -82,8 +87,8 @@ class Timecop
82
87
  time_klass = Time
83
88
  time_klass = Time.zone if Time.respond_to? :zone
84
89
  arg = args.shift
85
- if arg.is_a?(Time)
86
- if arg.respond_to?(:in_time_zone)
90
+ if arg.is_a?(Time)
91
+ if Timecop.active_support != false && arg.respond_to?(:in_time_zone)
87
92
  arg.in_time_zone
88
93
  else
89
94
  arg.getlocal
@@ -99,7 +104,7 @@ class Timecop
99
104
  elsif arg.nil?
100
105
  Time.now
101
106
  else
102
- if Time.respond_to?(:parse) && arg.is_a?(String)
107
+ if arg.is_a?(String) && Timecop.active_support != false && Time.respond_to?(:parse)
103
108
  Time.parse(arg)
104
109
  else
105
110
  # we'll just assume it's a list of y/m/d/h/m/s
@@ -13,78 +13,82 @@ require 'timecop/time_stack_item'
13
13
  class Timecop
14
14
  include Singleton
15
15
 
16
- # Allows you to run a block of code and "fake" a time throughout the execution of that block.
17
- # This is particularly useful for writing test methods where the passage of time is critical to the business
18
- # logic being tested. For example:
19
- #
20
- # joe = User.find(1)
21
- # joe.purchase_home()
22
- # assert !joe.mortgage_due?
23
- # Timecop.freeze(2008, 10, 5) do
24
- # assert joe.mortgage_due?
25
- # end
26
- #
27
- # freeze and travel will respond to several different arguments:
28
- # 1. Timecop.freeze(time_inst)
29
- # 2. Timecop.freeze(datetime_inst)
30
- # 3. Timecop.freeze(date_inst)
31
- # 4. Timecop.freeze(offset_in_seconds)
32
- # 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0)
33
- #
34
- # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their
35
- # previous values after the block has finished executing. This allows us to nest multiple
36
- # calls to Timecop.travel and have each block maintain it's concept of "now."
37
- #
38
- # * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if
39
- # benchmark or other timing calls are executed, which implicitly expect Time to actually move
40
- # forward.
41
- #
42
- # * Rails Users: Be especially careful when setting this in your development environment in a
43
- # rails project. Generators will load your environment, including the migration generator,
44
- # which will lead to files being generated with the timestamp set by the Timecop.freeze call
45
- # in your dev environment
46
- #
47
- # Returns the frozen time.
48
- def self.freeze(*args, &block)
49
- instance().send(:travel, :freeze, *args, &block)
50
- Time.now
51
- end
16
+ class << self
17
+ attr_accessor :active_support
18
+
19
+ # Allows you to run a block of code and "fake" a time throughout the execution of that block.
20
+ # This is particularly useful for writing test methods where the passage of time is critical to the business
21
+ # logic being tested. For example:
22
+ #
23
+ # joe = User.find(1)
24
+ # joe.purchase_home()
25
+ # assert !joe.mortgage_due?
26
+ # Timecop.freeze(2008, 10, 5) do
27
+ # assert joe.mortgage_due?
28
+ # end
29
+ #
30
+ # freeze and travel will respond to several different arguments:
31
+ # 1. Timecop.freeze(time_inst)
32
+ # 2. Timecop.freeze(datetime_inst)
33
+ # 3. Timecop.freeze(date_inst)
34
+ # 4. Timecop.freeze(offset_in_seconds)
35
+ # 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0)
36
+ #
37
+ # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their
38
+ # previous values after the block has finished executing. This allows us to nest multiple
39
+ # calls to Timecop.travel and have each block maintain it's concept of "now."
40
+ #
41
+ # * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if
42
+ # benchmark or other timing calls are executed, which implicitly expect Time to actually move
43
+ # forward.
44
+ #
45
+ # * Rails Users: Be especially careful when setting this in your development environment in a
46
+ # rails project. Generators will load your environment, including the migration generator,
47
+ # which will lead to files being generated with the timestamp set by the Timecop.freeze call
48
+ # in your dev environment
49
+ #
50
+ # Returns the value of the block or nil.
51
+ def freeze(*args, &block)
52
+ val = instance().send(:travel, :freeze, *args, &block)
53
+
54
+ block_given? ? val : nil
55
+ end
52
56
 
53
- # Allows you to run a block of code and "fake" a time throughout the execution of that block.
54
- # See Timecop#freeze for a sample of how to use (same exact usage syntax)
55
- #
56
- # * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly
57
- # good candidate for use in environment files in rails projects.
58
- #
59
- # Returns the 'new' current Time.
60
- def self.travel(*args, &block)
61
- instance().send(:travel, :travel, *args, &block)
62
- Time.now
63
- end
57
+ # Allows you to run a block of code and "fake" a time throughout the execution of that block.
58
+ # See Timecop#freeze for a sample of how to use (same exact usage syntax)
59
+ #
60
+ # * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly
61
+ # good candidate for use in environment files in rails projects.
62
+ #
63
+ # Returns the value of the block or nil.
64
+ def travel(*args, &block)
65
+ val = instance().send(:travel, :travel, *args, &block)
66
+
67
+ block_given? ? val : nil
68
+ end
64
69
 
65
- def self.baseline
66
- instance().send(:baseline)
67
- end
70
+ def baseline
71
+ instance().send(:baseline)
72
+ end
68
73
 
69
- def self.baseline=(baseline)
70
- instance().send(:baseline=, baseline)
71
- end
74
+ def baseline=(baseline)
75
+ instance().send(:baseline=, baseline)
76
+ end
72
77
 
73
- # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists).
74
- #
75
- # Returns Time.now, which is now the real current time.
76
- def self.return
77
- instance().send(:unmock!)
78
- Time.now
79
- end
78
+ # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists).
79
+ def return
80
+ instance().send(:unmock!)
81
+ nil
82
+ end
80
83
 
81
- def self.return_to_baseline
82
- instance().send(:return_to_baseline)
83
- Time.now
84
- end
84
+ def return_to_baseline
85
+ instance().send(:return_to_baseline)
86
+ Time.now
87
+ end
85
88
 
86
- def self.top_stack_item #:nodoc:
87
- instance().instance_variable_get(:@_stack).last
89
+ def top_stack_item #:nodoc:
90
+ instance().instance_variable_get(:@_stack).last
91
+ end
88
92
  end
89
93
 
90
94
  protected
@@ -5,6 +5,7 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
5
5
  class TestTimeStackItem < Test::Unit::TestCase
6
6
 
7
7
  def teardown
8
+ Timecop.active_support = nil
8
9
  Timecop.return
9
10
  end
10
11
 
@@ -182,19 +183,22 @@ class TestTimeStackItem < Test::Unit::TestCase
182
183
  Timecop.freeze(2011, 01, 02, hour=0, minute=0, second=0)
183
184
  end
184
185
 
185
- def test_integration_with_rails_time_zone
186
+ def test_parse_with_active_support_off
187
+ date = '2012-01-02'
188
+ Timecop.active_support = false
189
+ Time.expects(:parse).never
190
+ Timecop.freeze(date)
191
+ end
192
+
193
+ def test_uses_active_supports_in_time_zone
186
194
  time = Time.now
187
- def time.in_time_zone
188
- self - 3600
189
- end
190
- t = time - 3600
191
- stack_item = Timecop::TimeStackItem.new(:freeze, time)
192
- y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
193
- assert_equal y, stack_item.year
194
- assert_equal m, stack_item.month
195
- assert_equal d, stack_item.day
196
- assert_equal h, stack_item.hour
197
- assert_equal min, stack_item.min
198
- assert_equal s, stack_item.sec
195
+ Time.any_instance.expects(:in_time_zone).returns(time)
196
+ Timecop::TimeStackItem.new(:freeze, time)
197
+ end
198
+
199
+ def test_configured_off_active_support_in_time_zone_xxx
200
+ Timecop.active_support = false
201
+ Time.any_instance.expects(:in_time_zone).never
202
+ Timecop::TimeStackItem.new(:freeze, Time.now)
199
203
  end
200
204
  end
data/test/timecop_test.rb CHANGED
@@ -56,8 +56,47 @@ class TestTimecop < Test::Unit::TestCase
56
56
  end
57
57
 
58
58
  def test_travel_does_not_reduce_precision_of_datetime
59
- Timecop.travel(1)
60
- assert_not_equal DateTime.now, DateTime.now
59
+ # requires to_r on Float (>= 1.9)
60
+ if Float.method_defined?(:to_r)
61
+ Timecop.travel(1)
62
+ assert_not_equal DateTime.now, DateTime.now
63
+ end
64
+ end
65
+
66
+ def test_freeze_in_time_subclass_returns_mocked_subclass
67
+ t = Time.local(2008, 10, 10, 10, 10, 10)
68
+ custom_timeklass = Class.new(Time) do
69
+ def custom_format_method() strftime('%F') end
70
+ end
71
+ Timecop.freeze(2008, 10, 10, 10, 10, 10) do
72
+ assert custom_timeklass.now.is_a? custom_timeklass
73
+ assert Time.now.eql? custom_timeklass.now
74
+ assert custom_timeklass.now.respond_to? :custom_format_method
75
+ end
76
+ end
77
+
78
+ def test_freeze_in_date_subclass_returns_mocked_subclass
79
+ t = Time.local(2008, 10, 10, 10, 10, 10)
80
+ custom_dateklass = Class.new(Date) do
81
+ def custom_format_method() strftime('%F') end
82
+ end
83
+ Timecop.freeze(2008, 10, 10, 10, 10, 10) do
84
+ assert custom_dateklass.today.is_a? custom_dateklass
85
+ assert Date.today.eql? custom_dateklass.today
86
+ assert custom_dateklass.today.respond_to? :custom_format_method
87
+ end
88
+ end
89
+
90
+ def test_freeze_in_datetime_subclass_returns_mocked_subclass
91
+ t = Time.local(2008, 10, 10, 10, 10, 10)
92
+ custom_datetimeklass = Class.new(DateTime) do
93
+ def custom_format_method() strftime('%F') end
94
+ end
95
+ Timecop.freeze(2008, 10, 10, 10, 10, 10) do
96
+ assert custom_datetimeklass.now.is_a? custom_datetimeklass
97
+ assert DateTime.now.eql? custom_datetimeklass.now
98
+ assert custom_datetimeklass.now.respond_to? :custom_format_method
99
+ end
61
100
  end
62
101
 
63
102
  def test_recursive_freeze
@@ -285,29 +324,34 @@ class TestTimecop < Test::Unit::TestCase
285
324
  assert_nil Time.send(:mock_time)
286
325
  end
287
326
 
288
- def test_return_values_are_Time_instances
289
- assert Timecop.freeze.is_a?(Time)
290
- assert Timecop.travel.is_a?(Time)
291
- assert Timecop.return.is_a?(Time)
327
+ def test_travel_time_returns_nil
328
+ t_future = Time.local(2030, 10, 10, 10, 10, 10)
329
+ assert_nil Timecop.travel(t_future)
330
+ end
331
+
332
+ def test_travel_time_with_block_returns_the_value_of_the_block
333
+ t_future = Time.local(2030, 10, 10, 10, 10, 10)
334
+ expected = :foo
335
+ actual = Timecop.travel(t_future) { expected }
336
+
337
+ assert_equal expected, actual
292
338
  end
293
339
 
294
- def test_travel_time_returns_passed_value
340
+ def test_freeze_time_returns_nil
295
341
  t_future = Time.local(2030, 10, 10, 10, 10, 10)
296
- t_travel = Timecop.travel t_future
297
- assert times_effectively_equal(t_future, t_travel)
342
+ assert_nil Timecop.freeze(t_future)
298
343
  end
299
344
 
300
- def test_freeze_time_returns_passed_value
345
+ def test_freeze_time_with_block_returns_the_value_of_the_block
301
346
  t_future = Time.local(2030, 10, 10, 10, 10, 10)
302
- t_frozen = Timecop.freeze t_future
303
- assert times_effectively_equal(t_future, t_frozen)
347
+ expected = :foo
348
+ actual = Timecop.freeze(t_future) { expected }
349
+
350
+ assert_equal expected, actual
304
351
  end
305
352
 
306
- def test_return_time_returns_actual_time
307
- t_real = Time.now
308
- Timecop.freeze Time.local(2030, 10, 10, 10, 10, 10)
309
- t_return = Timecop.return
310
- assert times_effectively_equal(t_real, t_return)
353
+ def test_return_returns_nil
354
+ assert_nil Timecop.return
311
355
  end
312
356
 
313
357
  def test_freeze_without_params
@@ -319,6 +363,13 @@ class TestTimecop < Test::Unit::TestCase
319
363
  end
320
364
  end
321
365
 
366
+ def test_freeze_with_new_date
367
+ date = Date.new(2012, 6, 9)
368
+ Timecop.freeze(Date.new(2012, 6, 9)) do
369
+ assert_equal date, Time.now.__send__(:to_date)
370
+ end
371
+ end
372
+
322
373
  def test_return_to_baseline_without_a_baseline_set_returns_to_current_time
323
374
  time_before_travel = Time.now
324
375
  Timecop.travel Time.now - 60
metadata CHANGED
@@ -1,27 +1,35 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: timecop
3
- version: !ruby/object:Gem::Version
4
- version: 0.4.3
3
+ version: !ruby/object:Gem::Version
4
+ hash: 11
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Travis Jeffery
9
14
  - John Trupiano
10
15
  autorequire:
11
16
  bindir: bin
12
17
  cert_chain: []
13
- date: 2012-06-28 00:00:00.000000000 Z
18
+
19
+ date: 2012-09-05 00:00:00 -05:00
20
+ default_executable:
14
21
  dependencies: []
15
- description: A gem providing "time travel" and "time freezing" capabilities, making
16
- it dead simple to test time-dependent code. It provides a unified method to mock
17
- Time.now, Date.today, and DateTime.now in a single call.
22
+
23
+ description: A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call.
18
24
  email: travisjeffery@gmail.com
19
25
  executables: []
26
+
20
27
  extensions: []
21
- extra_rdoc_files:
28
+
29
+ extra_rdoc_files:
22
30
  - LICENSE
23
31
  - README.markdown
24
- files:
32
+ files:
25
33
  - History.rdoc
26
34
  - LICENSE
27
35
  - README.markdown
@@ -37,37 +45,43 @@ files:
37
45
  - test/timecop_test.rb
38
46
  - test/timecop_without_date_test.rb
39
47
  - test/timecop_without_date_but_with_time_test.rb
48
+ has_rdoc: true
40
49
  homepage: http://github.com/jtrupiano/timecop
41
50
  licenses: []
51
+
42
52
  post_install_message:
43
- rdoc_options:
53
+ rdoc_options:
44
54
  - --charset=UTF-8
45
- require_paths:
55
+ require_paths:
46
56
  - lib
47
- required_ruby_version: !ruby/object:Gem::Requirement
57
+ required_ruby_version: !ruby/object:Gem::Requirement
48
58
  none: false
49
- requirements:
50
- - - ! '>='
51
- - !ruby/object:Gem::Version
52
- version: '0'
53
- required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
67
  none: false
55
- requirements:
56
- - - ! '>='
57
- - !ruby/object:Gem::Version
58
- version: '0'
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
59
75
  requirements: []
76
+
60
77
  rubyforge_project: johntrupiano
61
- rubygems_version: 1.8.19
78
+ rubygems_version: 1.6.2
62
79
  signing_key:
63
80
  specification_version: 3
64
- summary: A gem providing "time travel" and "time freezing" capabilities, making it
65
- dead simple to test time-dependent code. It provides a unified method to mock Time.now,
66
- Date.today, and DateTime.now in a single call.
67
- test_files:
81
+ summary: A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call.
82
+ test_files:
68
83
  - test/test_helper.rb
69
84
  - test/time_stack_item_test.rb
70
85
  - test/timecop_test.rb
71
86
  - test/timecop_without_date_test.rb
72
87
  - test/timecop_without_date_but_with_time_test.rb
73
- has_rdoc: