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.
- data/{History.txt → History.rdoc} +13 -1
- data/README.rdoc +5 -5
- data/Rakefile +1 -1
- data/VERSION.yml +1 -1
- data/lib/timecop/time_extensions.rb +24 -36
- data/lib/timecop/time_stack_item.rb +64 -28
- data/lib/timecop/timecop.rb +5 -21
- data/test/test_helper.rb +46 -0
- data/test/test_time_stack_item.rb +86 -12
- data/test/test_timecop.rb +65 -73
- data/test/test_timecop_without_date.rb +14 -15
- metadata +5 -3
@@ -1,4 +1,4 @@
|
|
1
|
-
=== 0.3.
|
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
|
|
data/README.rdoc
CHANGED
@@ -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
|
-
*
|
65
|
-
*
|
66
|
-
*
|
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.
|
51
|
+
rdoc.rdoc_files.include('History.rdoc')
|
52
52
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
53
|
end
|
54
54
|
|
data/VERSION.yml
CHANGED
@@ -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
|
-
|
17
|
-
|
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
|
-
|
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
|
-
#
|
73
|
-
|
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
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
17
|
+
time.year
|
33
18
|
end
|
34
19
|
|
35
20
|
def month
|
36
|
-
|
21
|
+
time.month
|
37
22
|
end
|
38
23
|
|
39
24
|
def day
|
40
|
-
|
25
|
+
time.day
|
41
26
|
end
|
42
27
|
|
43
28
|
def hour
|
44
|
-
|
29
|
+
time.hour
|
45
30
|
end
|
46
31
|
|
47
32
|
def min
|
48
|
-
|
33
|
+
time.min
|
49
34
|
end
|
50
35
|
|
51
36
|
def sec
|
52
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/timecop/timecop.rb
CHANGED
@@ -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, :
|
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
|
data/test/test_helper.rb
ADDED
@@ -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 '
|
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
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
data/test/test_timecop.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
2
1
|
require 'date'
|
3
|
-
require '
|
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
|
-
|
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
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
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
|
-
|
204
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
229
|
-
|
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 '
|
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
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
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
|
-
|
86
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
113
|
-
|
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.
|
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-
|
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.
|
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
|