timecop 0.3.4.rc1 → 0.3.4.rc2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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