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.
- 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
|