timecop 0.3.4.rc1 → 0.3.4.rc2

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.
@@ -1,4 +1,4 @@
1
- === 0.3.2 / 2009-10-24
1
+ === 0.3.4 / unreleased (RC2 released 2009-11-28)
2
2
 
3
3
  * Maintenance
4
4
  * Fix various timezone-related issues. Notably, when traveling to a DateTime
@@ -8,6 +8,18 @@
8
8
  * Fix bug that would not allow Timecop to be used when Ruby's 'date'
9
9
  library had not been previously loaded.
10
10
  Code contributed by Tuomas Kareinen [tuomas]
11
+ * Fix bug when traveling to a DateTime across a DST boundary that
12
+ resulted in DateTime's being off by an hour.
13
+ * Migrate argument parsing into Timecop::TimeStackItem to reduce the
14
+ responsibility of the Timecop class.
15
+
16
+ === 0.3.3 2009-10-30
17
+
18
+ * Revoked due to regression.
19
+
20
+ === 0.3.2 / 2009-10-24
21
+
22
+ * Revoked due to regression.
11
23
 
12
24
  === 0.3.1 / 2009-09-30
13
25
 
@@ -1,6 +1,7 @@
1
1
  = timecop
2
2
 
3
- * http://github.com/jtrupiano/timecop
3
+ * Source[http://github.com/jtrupiano/timecop]
4
+ * Documentation[http://johntrupiano.rubyforge.org/timecop]
4
5
 
5
6
  == DESCRIPTION
6
7
 
@@ -61,7 +62,6 @@ in config/environments/test.rb
61
62
 
62
63
  == REFERENCES
63
64
 
64
- * "0.3.2 release":http://blog.smartlogicsolutions.com/2009/10/24/timecop-0-3-2-released/
65
- * "0.3.0 release":http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/
66
- * "0.2.0 release":http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/
67
- * "0.1.0 release":http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/
65
+ * {0.3.0 release}[http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/]
66
+ * {0.2.0 release}[http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/]
67
+ * {0.1.0 release}[http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/]
data/Rakefile CHANGED
@@ -48,7 +48,7 @@ Rake::RDocTask.new do |rdoc|
48
48
  rdoc.options << '--line-numbers' << '--inline-source'
49
49
  rdoc.title = "timecop #{version}"
50
50
  rdoc.rdoc_files.include('README*')
51
- rdoc.rdoc_files.include('History.txt')
51
+ rdoc.rdoc_files.include('History.rdoc')
52
52
  rdoc.rdoc_files.include('lib/**/*.rb')
53
53
  end
54
54
 
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :patch: 4
3
3
  :major: 0
4
- :build: rc1
4
+ :build: rc2
5
5
  :minor: 3
@@ -1,39 +1,10 @@
1
- #--
2
- # 1. Extensions to the Time, Date, and DateTime objects
3
- # 2. Allows us to "freeze" time in our Ruby applications.
4
- # 3. This is very useful when your app's functionality is dependent on time (e.g.
5
- # anything that might expire). This will allow us to alter the return value of
6
- # Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change.
7
1
 
8
2
  class Time #:nodoc:
9
3
  class << self
10
-
11
- @@mock_offset = nil
12
- @@mock_time = nil
13
-
14
4
  # Time we are behaving as
15
5
  def mock_time
16
- if !@@mock_offset.nil?
17
- now_without_mock_time - @@mock_offset
18
- else
19
- @@mock_time
20
- end
21
- end
22
-
23
- # Set new time to pretend we are.
24
- def freeze_time(new_now)
25
- @@mock_time = new_now
26
- @@mock_offset = nil
27
- end
28
-
29
- def move_time(new_now)
30
- @@mock_offset = new_now.nil? ? nil : (now_without_mock_time - new_now)
31
- @@mock_time = nil
32
- end
33
-
34
- # Restores Time to system clock
35
- def unmock!
36
- move_time(nil)
6
+ mocked_time_stack_item = Timecop.top_stack_item
7
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time
37
8
  end
38
9
 
39
10
  # Alias the original now
@@ -52,12 +23,18 @@ end
52
23
  if Object.const_defined?(:Date) && Date.respond_to?(:today)
53
24
  class Date #:nodoc:
54
25
  class << self
26
+ # Date we are behaving as
27
+ def mock_date
28
+ mocked_time_stack_item = Timecop.top_stack_item
29
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date
30
+ end
31
+
55
32
  # Alias the original today
56
33
  alias_method :today_without_mock_date, :today
57
34
 
58
35
  # Define today_with_mock_date
59
36
  def today_with_mock_date
60
- Time.now.send(:to_date)
37
+ mock_date || today_without_mock_date
61
38
  end
62
39
 
63
40
  # Alias today to today_with_mock_date
@@ -69,12 +46,23 @@ end
69
46
  if Object.const_defined?(:DateTime) && DateTime.respond_to?(:now)
70
47
  class DateTime #:nodoc:
71
48
  class << self
72
- # Alias the original now
73
- alias_method :now_without_mock_time, :now
74
-
49
+ # Time we are behaving as
50
+ def mock_time
51
+ mocked_time_stack_item = Timecop.top_stack_item
52
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime
53
+ end
54
+
55
+ # Fake alias :now_without_mock_time :now
56
+ # It appears that the DateTime library itself references Time.now
57
+ # for it's interpretation of now which caused
58
+ # DateTime.now_without_mock_time to incorrectly return the frozen time.
59
+ def now_without_mock_time
60
+ Time.now_without_mock_time.send :to_datetime
61
+ end
62
+
75
63
  # Define now_with_mock_time
76
64
  def now_with_mock_time
77
- Time.now.send(:to_datetime)
65
+ mock_time || now_without_mock_time
78
66
  end
79
67
 
80
68
  # Alias now to now_with_mock_time
@@ -6,54 +6,51 @@ class Timecop
6
6
 
7
7
  attr_reader :mock_type
8
8
  def initialize(mock_type, *args)
9
- @mock_type = mock_type
10
- arg = args.shift
11
- if arg.is_a?(Time)
12
- @time = arg.getlocal
13
- elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime)
14
- offset_difference = Time.now_without_mock_time.utc_offset - rational_to_utc_offset(arg.offset)
15
- @time = Time.local(arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec) + offset_difference
16
- elsif Object.const_defined?(:Date) && arg.is_a?(Date)
17
- @time = Time.local(arg.year, arg.month, arg.day, 0, 0, 0)
18
- elsif args.empty? && arg.kind_of?(Integer)
19
- @time = Time.now + arg
20
- else # we'll just assume it's a list of y/m/h/d/m/s
21
- year = arg || 0
22
- month = args.shift || 1
23
- day = args.shift || 1
24
- hour = args.shift || 0
25
- minute = args.shift || 0
26
- second = args.shift || 0
27
- @time = Time.local(year, month, day, hour, minute, second)
28
- end
9
+ raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel].include?(mock_type)
10
+ @mock_type = mock_type
11
+ @time = parse_time(*args)
12
+ @travel_offset = compute_travel_offset
13
+ @dst_adjustment = compute_dst_adjustment
29
14
  end
30
15
 
31
16
  def year
32
- @time.year
17
+ time.year
33
18
  end
34
19
 
35
20
  def month
36
- @time.month
21
+ time.month
37
22
  end
38
23
 
39
24
  def day
40
- @time.day
25
+ time.day
41
26
  end
42
27
 
43
28
  def hour
44
- @time.hour
29
+ time.hour
45
30
  end
46
31
 
47
32
  def min
48
- @time.min
33
+ time.min
49
34
  end
50
35
 
51
36
  def sec
52
- @time.sec
37
+ time.sec
38
+ end
39
+
40
+ def utc_offset
41
+ time.utc_offset
42
+ end
43
+
44
+ def travel_offset
45
+ @travel_offset
53
46
  end
54
47
 
55
48
  def time #:nodoc:
56
- @time
49
+ if travel_offset.nil?
50
+ @time
51
+ else
52
+ Time.now_without_mock_time + travel_offset
53
+ end
57
54
  end
58
55
 
59
56
  def date
@@ -61,7 +58,13 @@ class Timecop
61
58
  end
62
59
 
63
60
  def datetime
64
- time.send(:to_datetime)
61
+ # DateTime doesn't know about DST, so let's remove its presence
62
+ our_offset = utc_offset + dst_adjustment
63
+ DateTime.new(year, month, day, hour, min, sec, utc_offset_to_rational(our_offset))
64
+ end
65
+
66
+ def dst_adjustment
67
+ @dst_adjustment
65
68
  end
66
69
 
67
70
  private
@@ -73,5 +76,38 @@ class Timecop
73
76
  Rational(utc_offset, 24 * 60 * 60)
74
77
  end
75
78
 
79
+ def parse_time(*args)
80
+ arg = args.shift
81
+ if arg.is_a?(Time)
82
+ arg.getlocal
83
+ elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime)
84
+ offset_difference = Time.now.utc_offset - rational_to_utc_offset(arg.offset)
85
+ Time.local(arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec) + offset_difference
86
+ elsif Object.const_defined?(:Date) && arg.is_a?(Date)
87
+ Time.local(arg.year, arg.month, arg.day, 0, 0, 0)
88
+ elsif args.empty? && arg.kind_of?(Integer)
89
+ Time.now + arg
90
+ else # we'll just assume it's a list of y/m/d/h/m/s
91
+ year = arg || 0
92
+ month = args.shift || 1
93
+ day = args.shift || 1
94
+ hour = args.shift || 0
95
+ minute = args.shift || 0
96
+ second = args.shift || 0
97
+ Time.local(year, month, day, hour, minute, second)
98
+ end
99
+ end
100
+
101
+ def compute_dst_adjustment
102
+ return 0 if !(time.dst? ^ Time.now.dst?)
103
+ return -1 * 60 * 60 if time.dst?
104
+ return 60 * 60
105
+ end
106
+
107
+ def compute_travel_offset
108
+ return nil if mock_type == :freeze
109
+ @time - Time.now_without_mock_time
110
+ end
111
+
76
112
  end
77
113
  end
@@ -58,7 +58,7 @@ class Timecop
58
58
  #
59
59
  # Returns the 'new' current Time.
60
60
  def self.travel(*args, &block)
61
- instance().send(:travel, :move, *args, &block)
61
+ instance().send(:travel, :travel, *args, &block)
62
62
  Time.now
63
63
  end
64
64
 
@@ -69,6 +69,10 @@ class Timecop
69
69
  instance().send(:unmock!)
70
70
  Time.now
71
71
  end
72
+
73
+ def self.top_stack_item #:nodoc:
74
+ instance().instance_variable_get(:@_stack).last
75
+ end
72
76
 
73
77
  protected
74
78
 
@@ -78,8 +82,6 @@ class Timecop
78
82
 
79
83
  def travel(mock_type, *args, &block) #:nodoc:
80
84
  stack_item = TimeStackItem.new(mock_type, *args)
81
- # perform our action
82
- freeze_or_move(stack_item)
83
85
 
84
86
  # store this time traveling on our stack...
85
87
  @_stack << stack_item
@@ -90,30 +92,12 @@ class Timecop
90
92
  ensure
91
93
  # pull it off the stack...
92
94
  @_stack.pop
93
- if @_stack.size == 0
94
- # completely unmock if there's nothing to revert back to
95
- unmock!
96
- else
97
- # or reinstantiate the new the top of the stack (could be a :freeze or a :move)
98
- new_top = @_stack.last
99
- freeze_or_move(new_top)
100
- end
101
95
  end
102
96
  end
103
97
  end
104
98
 
105
99
  def unmock! #:nodoc:
106
100
  @_stack = []
107
- Time.unmock!
108
101
  end
109
102
 
110
- private
111
-
112
- def freeze_or_move(stack_item) #:nodoc:
113
- if stack_item.mock_type == :freeze
114
- Time.freeze_time(stack_item.time)
115
- else
116
- Time.move_time(stack_item.time)
117
- end
118
- end
119
103
  end
@@ -0,0 +1,46 @@
1
+ require 'test/unit'
2
+
3
+ class Test::Unit::TestCase
4
+ private
5
+ # Tests to see that two times are within the given distance,
6
+ # in seconds, from each other.
7
+ def times_effectively_equal(time1, time2, seconds_interval = 1)
8
+ (time1 - time2).abs <= seconds_interval
9
+ end
10
+
11
+ def assert_times_effectively_equal(time1, time2, seconds_interval = 1, msg = nil)
12
+ assert times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}"
13
+ end
14
+
15
+ def assert_times_effectively_not_equal(time1, time2, seconds_interval = 1, msg = nil)
16
+ assert !times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}"
17
+ end
18
+
19
+ def local_offset
20
+ DateTime.now_without_mock_time.offset
21
+ end
22
+
23
+ TIMEZONES = ["Europe/Paris", "UTC", "EDT"]
24
+
25
+ def each_timezone
26
+ old_tz = ENV["TZ"]
27
+
28
+ begin
29
+ TIMEZONES.each do |timezone|
30
+ ENV["TZ"] = timezone
31
+ yield
32
+ end
33
+ ensure
34
+ ENV["TZ"] = old_tz
35
+ end
36
+ end
37
+
38
+ def a_time_stack_item
39
+ Timecop::TimeStackItem.new(:freeze, 2008, 1, 1, 0, 0, 0)
40
+ end
41
+
42
+ def assert_date_times_equal(dt1, dt2)
43
+ assert_equal dt1, dt2, "Failed for timezone: #{ENV['TZ']}: #{dt1.to_s} not equal to #{dt2.to_s}"
44
+ end
45
+
46
+ end
@@ -1,9 +1,13 @@
1
1
  require 'date'
2
- require 'test/unit'
2
+ require 'test_helper'
3
3
  require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
4
4
 
5
5
  class TestTimeStackItem < Test::Unit::TestCase
6
6
 
7
+ def teardown
8
+ Timecop.return
9
+ end
10
+
7
11
  def test_new_with_time
8
12
  t = Time.now
9
13
  y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
@@ -15,7 +19,7 @@ class TestTimeStackItem < Test::Unit::TestCase
15
19
  assert_equal min, stack_item.min
16
20
  assert_equal s, stack_item.sec
17
21
  end
18
-
22
+
19
23
  def test_new_with_datetime_now
20
24
  t = DateTime.now
21
25
  y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
@@ -29,11 +33,13 @@ class TestTimeStackItem < Test::Unit::TestCase
29
33
  end
30
34
 
31
35
  def test_new_with_datetime_in_different_timezone
32
- t = DateTime.parse("2009-10-11 00:38:00 +0200")
33
- stack_item = Timecop::TimeStackItem.new(:freeze, t)
34
- assert_equal t, stack_item.datetime
36
+ each_timezone do
37
+ t = DateTime.parse("2009-10-11 00:38:00 +0200")
38
+ stack_item = Timecop::TimeStackItem.new(:freeze, t)
39
+ assert_date_times_equal(t, stack_item.datetime)
40
+ end
35
41
  end
36
-
42
+
37
43
  def test_new_with_date
38
44
  date = Date.today
39
45
  y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0
@@ -45,7 +51,7 @@ class TestTimeStackItem < Test::Unit::TestCase
45
51
  assert_equal min, stack_item.min
46
52
  assert_equal s, stack_item.sec
47
53
  end
48
-
54
+
49
55
  # Due to the nature of this test (calling Time.now once in this test and
50
56
  # once in #new), this test may fail when two subsequent calls
51
57
  # to Time.now return a different second.
@@ -60,7 +66,7 @@ class TestTimeStackItem < Test::Unit::TestCase
60
66
  assert_equal min, stack_item.min
61
67
  assert_equal s, stack_item.sec
62
68
  end
63
-
69
+
64
70
  def test_new_with_individual_arguments
65
71
  y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10
66
72
  stack_item = Timecop::TimeStackItem.new(:freeze, y, m, d, h, min, s)
@@ -86,8 +92,76 @@ class TestTimeStackItem < Test::Unit::TestCase
86
92
  assert_equal Rational(1, 24), a_time_stack_item.send(:utc_offset_to_rational, 3600)
87
93
  end
88
94
 
89
- private
90
- def a_time_stack_item
91
- Timecop::TimeStackItem.new(:freeze, 2008, 1, 1, 0, 0, 0)
92
- end
95
+ # Ensure DST adjustment is calculated properly for DateTime's
96
+ def test_compute_dst_adjustment_for_dst_to_dst
97
+ Timecop.freeze(DateTime.parse("2009-10-1 00:38:00 -0400"))
98
+ t = DateTime.parse("2009-10-11 00:00:00 -0400")
99
+ tsi = Timecop::TimeStackItem.new(:freeze, t)
100
+ assert Time.now.dst?, "precondition"
101
+ assert tsi.time.dst?, "precondition"
102
+ assert_equal 0, tsi.send(:dst_adjustment)
103
+ end
104
+
105
+ def test_compute_dst_adjustment_for_non_dst_to_non_dst
106
+ Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0400"))
107
+ t = DateTime.parse("2009-12-11 00:00:00 -0400")
108
+ tsi = Timecop::TimeStackItem.new(:freeze, t)
109
+ assert !Time.now.dst?, "precondition"
110
+ assert !tsi.time.dst?, "precondition"
111
+ assert_equal 0, tsi.send(:dst_adjustment)
112
+ end
113
+
114
+ def test_compute_dst_adjustment_for_dst_to_non_dst
115
+ Timecop.freeze(DateTime.parse("2009-10-1 00:38:00 -0400"))
116
+ t = DateTime.parse("2009-12-11 00:00:00 -0400")
117
+ tsi = Timecop::TimeStackItem.new(:freeze, t)
118
+ assert Time.now.dst?, "precondition"
119
+ assert !tsi.time.dst?, "precondition"
120
+ assert_equal 60 * 60, tsi.send(:dst_adjustment)
121
+ end
122
+
123
+ def test_compute_dst_adjustment_for_non_dst_to_dst
124
+ Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0400"))
125
+ t = DateTime.parse("2009-10-11 00:00:00 -0400")
126
+ tsi = Timecop::TimeStackItem.new(:freeze, t)
127
+ assert !Time.now.dst?, "precondition"
128
+ assert tsi.time.dst?, "precondition"
129
+ assert_equal -1 * 60 * 60, tsi.send(:dst_adjustment)
130
+ end
131
+
132
+ # Ensure DateTime's handle changing DST properly
133
+ def test_datetime_for_dst_to_non_dst
134
+ Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500"))
135
+ t = DateTime.parse("2009-10-11 00:00:00 -0400")
136
+ tsi = Timecop::TimeStackItem.new(:freeze, t)
137
+ assert_date_times_equal t, tsi.datetime
138
+ # verify Date also 'moves backward' an hour to change the day
139
+ assert_equal Date.new(2009, 10, 10), tsi.date
140
+ end
141
+
142
+ def test_datetime_for_non_dst_to_dst
143
+ Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 -0400"))
144
+ t = DateTime.parse("2009-11-30 23:38:00 -0500")
145
+ tsi = Timecop::TimeStackItem.new(:freeze, t)
146
+ assert_date_times_equal t, tsi.datetime
147
+ # verify Date also 'moves forward' an hour to change the day
148
+ assert_equal Date.new(2009, 12, 1), tsi.date
149
+ end
150
+
151
+ # Ensure @travel_offset is set properly
152
+ def test_set_travel_offset_for_travel
153
+ # Timecop.freeze(2009, 10, 1, 0, 0, 0)
154
+ t_now = Time.now
155
+ t = Time.local(2009, 10, 1, 0, 0, 30)
156
+ expected_offset = t - t_now
157
+ tsi = Timecop::TimeStackItem.new(:travel, t)
158
+ assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly"
159
+ end
160
+
161
+ def test_set_travel_offset_for_freeze
162
+ Timecop.freeze(2009, 10, 1, 0, 0, 0)
163
+ t = Time.local(2009, 10, 1, 0, 0, 30)
164
+ tsi = Timecop::TimeStackItem.new(:freeze, t)
165
+ assert_equal nil, tsi.send(:travel_offset)
166
+ end
93
167
  end
@@ -1,6 +1,5 @@
1
-
2
1
  require 'date'
3
- require 'test/unit'
2
+ require 'test_helper'
4
3
  require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
5
4
 
6
5
  class TestTimecop < Test::Unit::TestCase
@@ -67,7 +66,7 @@ class TestTimecop < Test::Unit::TestCase
67
66
  t = Time.local(2008, 10, 10, 10, 10, 10)
68
67
  Timecop.freeze(t) do
69
68
  assert_equal t, Time.now
70
- assert_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
69
+ assert_date_times_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
71
70
  assert_equal Date.new(2008, 10, 10), Date.today
72
71
  end
73
72
  assert_not_equal t, Time.now
@@ -75,16 +74,54 @@ class TestTimecop < Test::Unit::TestCase
75
74
  assert_not_equal Date.new(2008, 10, 10), Date.today
76
75
  end
77
76
 
78
- def test_freeze_with_datetime_instance_works_as_expected
79
- t = DateTime.new(2008, 10, 10, 10, 10, 10, local_offset)
80
- Timecop.freeze(t) do
81
- assert_equal t, DateTime.now
82
- assert_equal Time.local(2008, 10, 10, 10, 10, 10), Time.now
83
- assert_equal Date.new(2008, 10, 10), Date.today
77
+ def test_freeze_with_datetime_on_specific_timezone_during_dst
78
+ each_timezone do
79
+ # Start from a time that is subject to DST
80
+ Timecop.freeze(2009, 9, 1)
81
+ # Travel to a DateTime that is also in DST
82
+ t = DateTime.parse("2009-10-11 00:38:00 +0200")
83
+ Timecop.freeze(t) do
84
+ assert_date_times_equal t, DateTime.now
85
+ end
86
+ # Undo the original freeze
87
+ Timecop.return
84
88
  end
85
- assert_not_equal t, DateTime.now
86
- assert_not_equal Time.local(2008, 10, 10, 10, 10, 10), Time.now
87
- assert_not_equal Date.new(2008, 10, 10), Date.today
89
+ end
90
+
91
+ def test_freeze_with_datetime_on_specific_timezone_not_during_dst
92
+ each_timezone do
93
+ # Start from a time that is not subject to DST
94
+ Timecop.freeze(2009, 12, 1)
95
+ # Travel to a time that is also not in DST
96
+ t = DateTime.parse("2009-12-11 00:38:00 +0100")
97
+ Timecop.freeze(t) do
98
+ assert_date_times_equal t, DateTime.now
99
+ end
100
+ end
101
+ end
102
+
103
+ def test_freeze_with_datetime_from_a_non_dst_time_to_a_dst_time
104
+ each_timezone do
105
+ # Start from a time that is not subject to DST
106
+ Timecop.freeze(DateTime.parse("2009-12-1 00:00:00 +0100"))
107
+ # Travel back to a time in DST
108
+ t = DateTime.parse("2009-10-11 00:38:00 +0200")
109
+ Timecop.freeze(t) do
110
+ assert_date_times_equal t, DateTime.now
111
+ end
112
+ end
113
+ end
114
+
115
+ def test_freeze_with_datetime_from_a_dst_time_to_a_non_dst_time
116
+ each_timezone do
117
+ # Start from a time that is not subject to DST
118
+ Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 +0200"))
119
+ # Travel back to a time in DST
120
+ t = DateTime.parse("2009-12-1 00:38:00 +0100")
121
+ Timecop.freeze(t) do
122
+ assert_date_times_equal t, DateTime.now
123
+ end
124
+ end
88
125
  end
89
126
 
90
127
  def test_freeze_with_date_instance_works_as_expected
@@ -92,7 +129,7 @@ class TestTimecop < Test::Unit::TestCase
92
129
  Timecop.freeze(d) do
93
130
  assert_equal d, Date.today
94
131
  assert_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now
95
- assert_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now
132
+ assert_date_times_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now
96
133
  end
97
134
  assert_not_equal d, Date.today
98
135
  assert_not_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now
@@ -103,7 +140,7 @@ class TestTimecop < Test::Unit::TestCase
103
140
  t = Time.local(2008, 10, 10, 10, 10, 10)
104
141
  Timecop.freeze(t) do
105
142
  assert_equal t, Time.now
106
- assert_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
143
+ assert_date_times_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
107
144
  assert_equal Date.new(2008, 10, 10), Date.today
108
145
  Timecop.freeze(10) do
109
146
  assert_equal t + 10, Time.now
@@ -147,34 +184,13 @@ class TestTimecop < Test::Unit::TestCase
147
184
  t = Time.local(2008, 10, 10, 10, 10, 10)
148
185
  now = Time.now
149
186
  Timecop.travel(t) do
150
- #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened."
151
- assert Time.now - t < 2000, "Looks like we failed to actually travel time" # 2 seconds
152
- new_t = Time.now
153
- #sleep(10)
154
- assert_not_equal new_t, Time.now
155
- end
156
- end
157
-
158
- def test_freeze_with_datetime_on_specific_timezone_during_dst
159
- each_timezone do
160
- t = DateTime.parse("2009-10-11 00:38:00 +0200")
161
- assert_equal "+02:00", t.zone
162
- Timecop.freeze(t) do
163
- assert_equal t, DateTime.now.new_offset(t.offset), "Failed for timezone: #{ENV['TZ']}: #{t.to_s} not equal to #{DateTime.now.new_offset(t.offset).to_s}"
164
- end
187
+ new_now = Time.now
188
+ assert_times_effectively_equal(new_now, t, 1, "Looks like we failed to actually travel time")
189
+ sleep(0.25)
190
+ assert_times_effectively_not_equal new_now, Time.now, 0.25, "Looks like time is not moving"
165
191
  end
166
192
  end
167
193
 
168
- def test_freeze_with_datetime_on_specific_timezone_not_during_dst
169
- each_timezone do
170
- t = DateTime.parse("2009-12-11 00:38:00 +0200")
171
- assert_equal "+02:00", t.zone
172
- Timecop.freeze(t) do
173
- assert_equal t, DateTime.now.new_offset(t.offset), "Failed for timezone: #{ENV['TZ']}"
174
- end
175
- end
176
- end
177
-
178
194
  def test_mocked_date_time_now_is_local
179
195
  each_timezone do
180
196
  t = DateTime.parse("2009-10-11 00:38:00 +0200")
@@ -194,17 +210,18 @@ class TestTimecop < Test::Unit::TestCase
194
210
  end
195
211
  end
196
212
 
197
- def test_recursive_rebasing_maintains_each_context
213
+ def test_recursive_travel_maintains_each_context
198
214
  t = Time.local(2008, 10, 10, 10, 10, 10)
199
215
  Timecop.travel(2008, 10, 10, 10, 10, 10) do
200
216
  assert((t - Time.now).abs < 50, "Failed to travel time.")
201
217
  t2 = Time.local(2008, 9, 9, 9, 9, 9)
202
218
  Timecop.travel(2008, 9, 9, 9, 9, 9) do
203
- assert((t2 - Time.now) < 50, "Failed to travel time.")
204
- assert((t - Time.now) > 1000, "Failed to travel time.")
219
+ assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.")
220
+ assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.")
205
221
  end
206
- assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.")
222
+ assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.")
207
223
  end
224
+ assert_nil Time.send(:mock_time)
208
225
  end
209
226
 
210
227
  def test_recursive_travel_then_freeze
@@ -215,8 +232,9 @@ class TestTimecop < Test::Unit::TestCase
215
232
  Timecop.freeze(2008, 9, 9, 9, 9, 9) do
216
233
  assert_equal t2, Time.now
217
234
  end
218
- assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.")
235
+ assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.")
219
236
  end
237
+ assert_nil Time.send(:mock_time)
220
238
  end
221
239
 
222
240
  def test_recursive_freeze_then_travel
@@ -225,11 +243,12 @@ class TestTimecop < Test::Unit::TestCase
225
243
  assert_equal t, Time.now
226
244
  t2 = Time.local(2008, 9, 9, 9, 9, 9)
227
245
  Timecop.travel(t2) do
228
- assert((t2 - Time.now) < 50, "Failed to travel time.")
229
- assert((t - Time.now) > 1000, "Failed to travel time.")
246
+ assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.")
247
+ assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.")
230
248
  end
231
249
  assert_equal t, Time.now
232
250
  end
251
+ assert_nil Time.send(:mock_time)
233
252
  end
234
253
 
235
254
  def test_return_values_are_Time_instances
@@ -257,31 +276,4 @@ class TestTimecop < Test::Unit::TestCase
257
276
  assert times_effectively_equal(t_real, t_return)
258
277
  end
259
278
 
260
- private
261
-
262
- # Tests to see that two times are within the given distance,
263
- # in seconds, from each other.
264
- def times_effectively_equal(time1, time2, seconds_interval = 1)
265
- (time1.to_i - time2.to_i).abs <= seconds_interval
266
- end
267
-
268
- def local_offset
269
- DateTime.now_without_mock_time.offset
270
- end
271
-
272
- TIMEZONES = ["Europe/Paris", "UTC", "EDT"]
273
-
274
- def each_timezone
275
- old_tz = ENV["TZ"]
276
-
277
- begin
278
- TIMEZONES.each do |timezone|
279
- ENV["TZ"] = timezone
280
- yield
281
- end
282
- ensure
283
- ENV["TZ"] = old_tz
284
- end
285
- end
286
-
287
279
  end
@@ -1,5 +1,5 @@
1
1
 
2
- require 'test/unit'
2
+ require 'test_helper'
3
3
  require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
4
4
 
5
5
  class TestTimecopWithoutDate < Test::Unit::TestCase
@@ -56,10 +56,10 @@ class TestTimecopWithoutDate < Test::Unit::TestCase
56
56
  t = Time.local(2008, 10, 10, 10, 10, 10)
57
57
  now = Time.now
58
58
  Timecop.freeze(t) do
59
- #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened."
59
+ sleep(0.25)
60
+ assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened."
60
61
  new_t = Time.now
61
62
  assert_equal t, new_t, "Failed to change move time." # 2 seconds
62
- #sleep(10)
63
63
  assert_equal new_t, Time.now
64
64
  end
65
65
  end
@@ -68,24 +68,23 @@ class TestTimecopWithoutDate < Test::Unit::TestCase
68
68
  t = Time.local(2008, 10, 10, 10, 10, 10)
69
69
  now = Time.now
70
70
  Timecop.travel(t) do
71
- #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened."
72
- assert Time.now - t < 2000, "Looks like we failed to actually travel time" # 2 seconds
73
- new_t = Time.now
74
- #sleep(10)
75
- assert_not_equal new_t, Time.now
71
+ new_now = Time.now
72
+ assert_times_effectively_equal new_now, t, 1, "Looks like we failed to actually travel time" # 0.1 seconds
73
+ sleep(0.25)
74
+ assert_times_effectively_not_equal new_now, Time.now, 0.25, "Looks like time is not moving"
76
75
  end
77
76
  end
78
77
 
79
- def test_recursive_rebasing_maintains_each_context
78
+ def test_recursive_travel_maintains_each_context
80
79
  t = Time.local(2008, 10, 10, 10, 10, 10)
81
80
  Timecop.travel(2008, 10, 10, 10, 10, 10) do
82
81
  assert((t - Time.now).abs < 50, "Failed to travel time.")
83
82
  t2 = Time.local(2008, 9, 9, 9, 9, 9)
84
83
  Timecop.travel(2008, 9, 9, 9, 9, 9) do
85
- assert((t2 - Time.now) < 50, "Failed to travel time.")
86
- assert((t - Time.now) > 1000, "Failed to travel time.")
84
+ assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.")
85
+ assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.")
87
86
  end
88
- assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.")
87
+ assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.")
89
88
  end
90
89
  assert_nil Time.send(:mock_time)
91
90
  end
@@ -98,7 +97,7 @@ class TestTimecopWithoutDate < Test::Unit::TestCase
98
97
  Timecop.freeze(2008, 9, 9, 9, 9, 9) do
99
98
  assert_equal t2, Time.now
100
99
  end
101
- assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.")
100
+ assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.")
102
101
  end
103
102
  assert_nil Time.send(:mock_time)
104
103
  end
@@ -109,8 +108,8 @@ class TestTimecopWithoutDate < Test::Unit::TestCase
109
108
  assert_equal t, Time.now
110
109
  t2 = Time.local(2008, 9, 9, 9, 9, 9)
111
110
  Timecop.travel(t2) do
112
- assert((t2 - Time.now) < 50, "Failed to travel time.")
113
- assert((t - Time.now) > 1000, "Failed to travel time.")
111
+ assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.")
112
+ assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.")
114
113
  end
115
114
  assert_equal t, Time.now
116
115
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timecop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4.rc1
4
+ version: 0.3.4.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Trupiano
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-03 00:00:00 -05:00
12
+ date: 2009-11-28 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -23,7 +23,7 @@ extra_rdoc_files:
23
23
  - LICENSE
24
24
  - README.rdoc
25
25
  files:
26
- - History.txt
26
+ - History.rdoc
27
27
  - LICENSE
28
28
  - README.rdoc
29
29
  - Rakefile
@@ -33,6 +33,7 @@ files:
33
33
  - lib/timecop/time_stack_item.rb
34
34
  - lib/timecop/timecop.rb
35
35
  - test/run_tests.sh
36
+ - test/test_helper.rb
36
37
  - test/test_time_stack_item.rb
37
38
  - test/test_timecop.rb
38
39
  - test/test_timecop_without_date.rb
@@ -66,6 +67,7 @@ signing_key:
66
67
  specification_version: 3
67
68
  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.
68
69
  test_files:
70
+ - test/test_helper.rb
69
71
  - test/test_time_stack_item.rb
70
72
  - test/test_timecop.rb
71
73
  - test/test_timecop_without_date.rb