timecop 0.3.1 → 0.3.4
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} +24 -1
- data/README.rdoc +11 -12
- data/Rakefile +3 -2
- data/VERSION.yml +2 -2
- data/lib/timecop/time_extensions.rb +21 -46
- data/lib/timecop/time_stack_item.rb +113 -0
- data/lib/timecop/timecop.rb +7 -57
- data/test/run_tests.sh +5 -2
- data/test/test_helper.rb +46 -0
- data/test/test_time_stack_item.rb +167 -0
- data/test/test_timecop.rb +86 -37
- data/test/test_timecop_without_date.rb +15 -16
- data/test/test_timecop_without_date_but_with_time.rb +12 -0
- metadata +10 -6
- data/lib/timecop/stack_item.rb +0 -12
- data/test/test_timecop_internals.rb +0 -69
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
=== 0.3.4 / unreleased (RC2 released 2009-11-28)
|
|
2
|
+
|
|
3
|
+
* Maintenance
|
|
4
|
+
* Fix various timezone-related issues. Notably, when traveling to a DateTime
|
|
5
|
+
instance specified in a non-local timezone, convert provided DateTime
|
|
6
|
+
instance to a local instance and return that from DateTime.now.
|
|
7
|
+
Code contributed by Michaël Witrant [piglop]
|
|
8
|
+
* Fix bug that would not allow Timecop to be used when Ruby's 'date'
|
|
9
|
+
library had not been previously loaded.
|
|
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.
|
|
23
|
+
|
|
1
24
|
=== 0.3.1 / 2009-09-30
|
|
2
25
|
|
|
3
26
|
* Maintenance
|
|
@@ -7,7 +30,7 @@
|
|
|
7
30
|
|
|
8
31
|
* API
|
|
9
32
|
* Completely remove Timecop#unset_all (deprecated by Timecop#return in 0.2.0)
|
|
10
|
-
* Return Time.now from #freeze, #travel and #return -- code contributed by Keith Bennett
|
|
33
|
+
* Return Time.now from #freeze, #travel and #return -- code contributed by Keith Bennett [keithrbennett]
|
|
11
34
|
|
|
12
35
|
* Maintenance
|
|
13
36
|
* Fix bug that left Time#mock_time set in some instances
|
data/README.rdoc
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
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
|
|
|
7
8
|
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.
|
|
8
9
|
|
|
10
|
+
== INSTALL
|
|
11
|
+
|
|
12
|
+
gem install timecop
|
|
13
|
+
|
|
9
14
|
== FEATURES
|
|
10
15
|
|
|
11
16
|
* Freeze time to a specific point.
|
|
12
17
|
* Travel back to a specific point in time, but allow time to continue moving forward from there.
|
|
18
|
+
* No dependencies, can be used with _any_ ruby project
|
|
13
19
|
* Timecop api allows arguments to be passed into #freeze and #travel as one of the following:
|
|
14
20
|
* Time instance
|
|
15
21
|
* DateTime instance
|
|
@@ -54,16 +60,9 @@ in config/environments/test.rb
|
|
|
54
60
|
sleep(10)
|
|
55
61
|
new_time == Time.now # ==> false
|
|
56
62
|
|
|
57
|
-
== DEPENDENCIES
|
|
58
|
-
|
|
59
|
-
* None
|
|
60
|
-
|
|
61
|
-
== INSTALL
|
|
62
|
-
|
|
63
|
-
* sudo gem install timecop (latest stable version from rubyforge)
|
|
64
|
-
* sudo gem install jtrupiano-timecop (HEAD of the repo from github)
|
|
65
|
-
|
|
66
63
|
== REFERENCES
|
|
67
64
|
|
|
68
|
-
*
|
|
69
|
-
*
|
|
65
|
+
* {0.3.4 release}[http://blog.smartlogicsolutions.com/2009/12/07/timecop-0-3-4-released/]
|
|
66
|
+
* {0.3.0 release}[http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/]
|
|
67
|
+
* {0.2.0 release}[http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/]
|
|
68
|
+
* {0.1.0 release}[http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/]
|
data/Rakefile
CHANGED
|
@@ -2,7 +2,7 @@ require 'rake'
|
|
|
2
2
|
require 'rake/testtask'
|
|
3
3
|
require 'rake/rdoctask'
|
|
4
4
|
|
|
5
|
-
gem 'jeweler', '~> 1.
|
|
5
|
+
gem 'jeweler', '~> 1.3.0'
|
|
6
6
|
|
|
7
7
|
begin
|
|
8
8
|
require 'jeweler'
|
|
@@ -16,6 +16,7 @@ begin
|
|
|
16
16
|
s.authors = ["John Trupiano"]
|
|
17
17
|
s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"]
|
|
18
18
|
end
|
|
19
|
+
Jeweler::GemcutterTasks.new
|
|
19
20
|
Jeweler::RubyforgeTasks.new do |rubyforge|
|
|
20
21
|
rubyforge.doc_task = "rdoc"
|
|
21
22
|
rubyforge.remote_doc_path = "timecop"
|
|
@@ -47,7 +48,7 @@ Rake::RDocTask.new do |rdoc|
|
|
|
47
48
|
rdoc.options << '--line-numbers' << '--inline-source'
|
|
48
49
|
rdoc.title = "timecop #{version}"
|
|
49
50
|
rdoc.rdoc_files.include('README*')
|
|
50
|
-
rdoc.rdoc_files.include('History.
|
|
51
|
+
rdoc.rdoc_files.include('History.rdoc')
|
|
51
52
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
52
53
|
end
|
|
53
54
|
|
data/VERSION.yml
CHANGED
|
@@ -1,40 +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
|
-
# Time we
|
|
11
|
-
#attr_reader :mock_time
|
|
12
|
-
|
|
13
|
-
@@mock_offset = nil
|
|
14
|
-
@@mock_time = nil
|
|
15
|
-
|
|
4
|
+
# Time we are behaving as
|
|
16
5
|
def mock_time
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
else
|
|
20
|
-
@@mock_time
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Set new time to pretend we are.
|
|
25
|
-
def freeze_time(new_now)
|
|
26
|
-
@@mock_time = new_now
|
|
27
|
-
@@mock_offset = nil
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def move_time(new_now)
|
|
31
|
-
@@mock_offset = new_now.nil? ? nil : (now_without_mock_time - new_now)
|
|
32
|
-
@@mock_time = nil
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Restores Time to system clock
|
|
36
|
-
def unmock!
|
|
37
|
-
move_time(nil)
|
|
6
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
|
7
|
+
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time
|
|
38
8
|
end
|
|
39
9
|
|
|
40
10
|
# Alias the original now
|
|
@@ -50,15 +20,15 @@ class Time #:nodoc:
|
|
|
50
20
|
end
|
|
51
21
|
end
|
|
52
22
|
|
|
53
|
-
if Object.const_defined?(:Date)
|
|
23
|
+
if Object.const_defined?(:Date) && Date.respond_to?(:today)
|
|
54
24
|
class Date #:nodoc:
|
|
55
25
|
class << self
|
|
26
|
+
# Date we are behaving as
|
|
56
27
|
def mock_date
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Date.new(now.year, now.month, now.day)
|
|
28
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
|
29
|
+
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date
|
|
60
30
|
end
|
|
61
|
-
|
|
31
|
+
|
|
62
32
|
# Alias the original today
|
|
63
33
|
alias_method :today_without_mock_date, :today
|
|
64
34
|
|
|
@@ -73,18 +43,23 @@ if Object.const_defined?(:Date)
|
|
|
73
43
|
end
|
|
74
44
|
end
|
|
75
45
|
|
|
76
|
-
if Object.const_defined?(:DateTime)
|
|
46
|
+
if Object.const_defined?(:DateTime) && DateTime.respond_to?(:now)
|
|
77
47
|
class DateTime #:nodoc:
|
|
78
48
|
class << self
|
|
49
|
+
# Time we are behaving as
|
|
79
50
|
def mock_time
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
DateTime.new(t_now.year, t_now.month, t_now.day, t_now.hour, t_now.min, t_now.sec)
|
|
51
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
|
52
|
+
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime
|
|
83
53
|
end
|
|
84
|
-
|
|
85
|
-
#
|
|
86
|
-
|
|
87
|
-
|
|
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
|
+
|
|
88
63
|
# Define now_with_mock_time
|
|
89
64
|
def now_with_mock_time
|
|
90
65
|
mock_time || now_without_mock_time
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
|
|
2
|
+
class Timecop
|
|
3
|
+
# A data class for carrying around "time movement" objects. Makes it easy to keep track of the time
|
|
4
|
+
# movements on a simple stack.
|
|
5
|
+
class TimeStackItem #:nodoc:
|
|
6
|
+
|
|
7
|
+
attr_reader :mock_type
|
|
8
|
+
def initialize(mock_type, *args)
|
|
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
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def year
|
|
17
|
+
time.year
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def month
|
|
21
|
+
time.month
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def day
|
|
25
|
+
time.day
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def hour
|
|
29
|
+
time.hour
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def min
|
|
33
|
+
time.min
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def 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
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def time #:nodoc:
|
|
49
|
+
if travel_offset.nil?
|
|
50
|
+
@time
|
|
51
|
+
else
|
|
52
|
+
Time.now_without_mock_time + travel_offset
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def date
|
|
57
|
+
time.send(:to_date)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def 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
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
def rational_to_utc_offset(rational)
|
|
72
|
+
((24.0 / rational.denominator) * rational.numerator) * (60 * 60)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def utc_offset_to_rational(utc_offset)
|
|
76
|
+
Rational(utc_offset, 24 * 60 * 60)
|
|
77
|
+
end
|
|
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
|
+
|
|
112
|
+
end
|
|
113
|
+
end
|
data/lib/timecop/timecop.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'singleton'
|
|
2
2
|
require File.join(File.dirname(__FILE__), 'time_extensions')
|
|
3
|
-
require File.join(File.dirname(__FILE__), '
|
|
3
|
+
require File.join(File.dirname(__FILE__), 'time_stack_item')
|
|
4
4
|
|
|
5
5
|
# Timecop
|
|
6
6
|
# * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects
|
|
@@ -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
|
|
|
@@ -77,12 +81,7 @@ class Timecop
|
|
|
77
81
|
end
|
|
78
82
|
|
|
79
83
|
def travel(mock_type, *args, &block) #:nodoc:
|
|
80
|
-
|
|
81
|
-
year, month, day, hour, minute, second = parse_travel_args(*args)
|
|
82
|
-
|
|
83
|
-
stack_item = StackItem.new(mock_type, year, month, day, hour, minute, second)
|
|
84
|
-
# perform our action
|
|
85
|
-
freeze_or_move(stack_item)
|
|
84
|
+
stack_item = TimeStackItem.new(mock_type, *args)
|
|
86
85
|
|
|
87
86
|
# store this time traveling on our stack...
|
|
88
87
|
@_stack << stack_item
|
|
@@ -93,61 +92,12 @@ class Timecop
|
|
|
93
92
|
ensure
|
|
94
93
|
# pull it off the stack...
|
|
95
94
|
@_stack.pop
|
|
96
|
-
if @_stack.size == 0
|
|
97
|
-
# completely unmock if there's nothing to revert back to
|
|
98
|
-
unmock!
|
|
99
|
-
else
|
|
100
|
-
# or reinstantiate the new the top of the stack (could be a :freeze or a :move)
|
|
101
|
-
new_top = @_stack.last
|
|
102
|
-
freeze_or_move(new_top)
|
|
103
|
-
end
|
|
104
95
|
end
|
|
105
96
|
end
|
|
106
97
|
end
|
|
107
98
|
|
|
108
99
|
def unmock! #:nodoc:
|
|
109
100
|
@_stack = []
|
|
110
|
-
Time.unmock!
|
|
111
101
|
end
|
|
112
102
|
|
|
113
|
-
private
|
|
114
|
-
|
|
115
|
-
def freeze_or_move(stack_item) #:nodoc:
|
|
116
|
-
if stack_item.mock_type == :freeze
|
|
117
|
-
Time.freeze_time(time_for_stack_item(stack_item))
|
|
118
|
-
else
|
|
119
|
-
Time.move_time(time_for_stack_item(stack_item))
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def time_for_stack_item(stack_item) #:nodoc:
|
|
124
|
-
if Time.respond_to?(:zone) && !Time.zone.nil?
|
|
125
|
-
# ActiveSupport loaded
|
|
126
|
-
time = Time.zone.local(stack_item.year, stack_item.month, stack_item.day, stack_item.hour, stack_item.minute, stack_item.second)
|
|
127
|
-
else
|
|
128
|
-
# ActiveSupport not loaded
|
|
129
|
-
time = Time.local(stack_item.year, stack_item.month, stack_item.day, stack_item.hour, stack_item.minute, stack_item.second)
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def parse_travel_args(*args) #:nodoc:
|
|
134
|
-
arg = args.shift
|
|
135
|
-
if arg.is_a?(Time) || (Object.const_defined?(:DateTime) && arg.is_a?(DateTime))
|
|
136
|
-
year, month, day, hour, minute, second = arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec
|
|
137
|
-
elsif Object.const_defined?(:Date) && arg.is_a?(Date)
|
|
138
|
-
year, month, day, hour, minute, second = arg.year, arg.month, arg.day, 0, 0, 0
|
|
139
|
-
#puts "#{year}-#{month}-#{day} #{hour}:#{minute}:#{second}"
|
|
140
|
-
elsif args.empty? && arg.kind_of?(Integer)
|
|
141
|
-
t = Time.now + arg
|
|
142
|
-
year, month, day, hour, minute, second = t.year, t.month, t.day, t.hour, t.min, t.sec
|
|
143
|
-
else # we'll just assume it's a list of y/m/h/d/m/s
|
|
144
|
-
year = arg || 0
|
|
145
|
-
month = args.shift || 1
|
|
146
|
-
day = args.shift || 1
|
|
147
|
-
hour = args.shift || 0
|
|
148
|
-
minute = args.shift || 0
|
|
149
|
-
second = args.shift || 0
|
|
150
|
-
end
|
|
151
|
-
return year, month, day, hour, minute, second
|
|
152
|
-
end
|
|
153
103
|
end
|
data/test/run_tests.sh
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
|
|
3
|
-
echo "\033[1;81m Running
|
|
4
|
-
ruby
|
|
3
|
+
echo "\033[1;81m Running test_time_stack_item...\033[0m"
|
|
4
|
+
ruby test_time_stack_item.rb || (echo "FAILED!!!!!!!!!!!!")
|
|
5
5
|
|
|
6
6
|
echo "\033[1;81m Running test_timecop_without_date...\033[0m"
|
|
7
7
|
ruby test_timecop_without_date.rb || (echo "FAILED!!!!!!!!!!!!")
|
|
8
8
|
|
|
9
|
+
echo "\033[1;81m Running test_timecop_without_date_but_with_time...\033[0m"
|
|
10
|
+
ruby test_timecop_without_date_but_with_time.rb || (echo "FAILED!!!!!!!!!!!!")
|
|
11
|
+
|
|
9
12
|
echo "\033[1;81m Running test_timecop...\033[0m"
|
|
10
13
|
ruby test_timecop.rb || (echo "FAILED!!!!!!!!!!!!")
|
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
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
|
|
4
|
+
|
|
5
|
+
class TestTimeStackItem < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
def teardown
|
|
8
|
+
Timecop.return
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_new_with_time
|
|
12
|
+
t = Time.now
|
|
13
|
+
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
|
14
|
+
stack_item = Timecop::TimeStackItem.new(:freeze, t)
|
|
15
|
+
assert_equal y, stack_item.year
|
|
16
|
+
assert_equal m, stack_item.month
|
|
17
|
+
assert_equal d, stack_item.day
|
|
18
|
+
assert_equal h, stack_item.hour
|
|
19
|
+
assert_equal min, stack_item.min
|
|
20
|
+
assert_equal s, stack_item.sec
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_new_with_datetime_now
|
|
24
|
+
t = DateTime.now
|
|
25
|
+
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
|
26
|
+
stack_item = Timecop::TimeStackItem.new(:freeze, t)
|
|
27
|
+
assert_equal y, stack_item.year
|
|
28
|
+
assert_equal m, stack_item.month
|
|
29
|
+
assert_equal d, stack_item.day
|
|
30
|
+
assert_equal h, stack_item.hour
|
|
31
|
+
assert_equal min, stack_item.min
|
|
32
|
+
assert_equal s, stack_item.sec
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_new_with_datetime_in_different_timezone
|
|
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
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_new_with_date
|
|
44
|
+
date = Date.today
|
|
45
|
+
y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0
|
|
46
|
+
stack_item = Timecop::TimeStackItem.new(:freeze, date)
|
|
47
|
+
assert_equal y, stack_item.year
|
|
48
|
+
assert_equal m, stack_item.month
|
|
49
|
+
assert_equal d, stack_item.day
|
|
50
|
+
assert_equal h, stack_item.hour
|
|
51
|
+
assert_equal min, stack_item.min
|
|
52
|
+
assert_equal s, stack_item.sec
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Due to the nature of this test (calling Time.now once in this test and
|
|
56
|
+
# once in #new), this test may fail when two subsequent calls
|
|
57
|
+
# to Time.now return a different second.
|
|
58
|
+
def test_new_with_integer
|
|
59
|
+
t = Time.now
|
|
60
|
+
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
|
61
|
+
stack_item = Timecop::TimeStackItem.new(:freeze, 0)
|
|
62
|
+
assert_equal y, stack_item.year
|
|
63
|
+
assert_equal m, stack_item.month
|
|
64
|
+
assert_equal d, stack_item.day
|
|
65
|
+
assert_equal h, stack_item.hour
|
|
66
|
+
assert_equal min, stack_item.min
|
|
67
|
+
assert_equal s, stack_item.sec
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def test_new_with_individual_arguments
|
|
71
|
+
y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10
|
|
72
|
+
stack_item = Timecop::TimeStackItem.new(:freeze, y, m, d, h, min, s)
|
|
73
|
+
assert_equal y, stack_item.year
|
|
74
|
+
assert_equal m, stack_item.month
|
|
75
|
+
assert_equal d, stack_item.day
|
|
76
|
+
assert_equal h, stack_item.hour
|
|
77
|
+
assert_equal min, stack_item.min
|
|
78
|
+
assert_equal s, stack_item.sec
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_rational_to_utc_offset
|
|
82
|
+
assert_equal -14400, a_time_stack_item.send(:rational_to_utc_offset, Rational(-1, 6))
|
|
83
|
+
assert_equal -18000, a_time_stack_item.send(:rational_to_utc_offset, Rational(-5, 24))
|
|
84
|
+
assert_equal 0, a_time_stack_item.send(:rational_to_utc_offset, Rational(0, 1))
|
|
85
|
+
assert_equal 3600, a_time_stack_item.send(:rational_to_utc_offset, Rational(1, 24))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_utc_offset_to_rational
|
|
89
|
+
assert_equal Rational(-1, 6), a_time_stack_item.send(:utc_offset_to_rational, -14400)
|
|
90
|
+
assert_equal Rational(-5, 24), a_time_stack_item.send(:utc_offset_to_rational, -18000)
|
|
91
|
+
assert_equal Rational(0, 1), a_time_stack_item.send(:utc_offset_to_rational, 0)
|
|
92
|
+
assert_equal Rational(1, 24), a_time_stack_item.send(:utc_offset_to_rational, 3600)
|
|
93
|
+
end
|
|
94
|
+
|
|
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
|
|
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,24 +66,62 @@ 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
|
|
74
|
-
assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now
|
|
73
|
+
assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
|
|
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,18 +129,18 @@ 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
|
|
99
|
-
assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0), DateTime.now
|
|
136
|
+
assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now
|
|
100
137
|
end
|
|
101
138
|
|
|
102
139
|
def test_freeze_with_integer_instance_works_as_expected
|
|
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,25 +184,44 @@ 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
|
-
|
|
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"
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def test_mocked_date_time_now_is_local
|
|
195
|
+
each_timezone do
|
|
196
|
+
t = DateTime.parse("2009-10-11 00:38:00 +0200")
|
|
197
|
+
Timecop.freeze(t) do
|
|
198
|
+
assert_equal local_offset, DateTime.now.offset, "Failed for timezone: #{ENV['TZ']}"
|
|
199
|
+
end
|
|
155
200
|
end
|
|
156
201
|
end
|
|
157
202
|
|
|
158
|
-
def
|
|
203
|
+
def test_freeze_with_utc_time
|
|
204
|
+
each_timezone do
|
|
205
|
+
t = Time.utc(2008, 10, 10, 10, 10, 10)
|
|
206
|
+
local = t.getlocal
|
|
207
|
+
Timecop.freeze(t) do
|
|
208
|
+
assert_equal local, Time.now, "Failed for timezone: #{ENV['TZ']}"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def test_recursive_travel_maintains_each_context
|
|
159
214
|
t = Time.local(2008, 10, 10, 10, 10, 10)
|
|
160
215
|
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
|
161
216
|
assert((t - Time.now).abs < 50, "Failed to travel time.")
|
|
162
217
|
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
|
163
218
|
Timecop.travel(2008, 9, 9, 9, 9, 9) do
|
|
164
|
-
|
|
165
|
-
|
|
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.")
|
|
166
221
|
end
|
|
167
|
-
|
|
222
|
+
assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.")
|
|
168
223
|
end
|
|
224
|
+
assert_nil Time.send(:mock_time)
|
|
169
225
|
end
|
|
170
226
|
|
|
171
227
|
def test_recursive_travel_then_freeze
|
|
@@ -176,8 +232,9 @@ class TestTimecop < Test::Unit::TestCase
|
|
|
176
232
|
Timecop.freeze(2008, 9, 9, 9, 9, 9) do
|
|
177
233
|
assert_equal t2, Time.now
|
|
178
234
|
end
|
|
179
|
-
|
|
235
|
+
assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.")
|
|
180
236
|
end
|
|
237
|
+
assert_nil Time.send(:mock_time)
|
|
181
238
|
end
|
|
182
239
|
|
|
183
240
|
def test_recursive_freeze_then_travel
|
|
@@ -186,11 +243,12 @@ class TestTimecop < Test::Unit::TestCase
|
|
|
186
243
|
assert_equal t, Time.now
|
|
187
244
|
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
|
188
245
|
Timecop.travel(t2) do
|
|
189
|
-
|
|
190
|
-
|
|
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.")
|
|
191
248
|
end
|
|
192
249
|
assert_equal t, Time.now
|
|
193
250
|
end
|
|
251
|
+
assert_nil Time.send(:mock_time)
|
|
194
252
|
end
|
|
195
253
|
|
|
196
254
|
def test_return_values_are_Time_instances
|
|
@@ -218,13 +276,4 @@ class TestTimecop < Test::Unit::TestCase
|
|
|
218
276
|
assert times_effectively_equal(t_real, t_return)
|
|
219
277
|
end
|
|
220
278
|
|
|
221
|
-
|
|
222
|
-
private
|
|
223
|
-
|
|
224
|
-
# Tests to see that two times are within the given distance,
|
|
225
|
-
# in seconds, from each other.
|
|
226
|
-
def times_effectively_equal(time1, time2, seconds_interval = 1)
|
|
227
|
-
(time1.to_i - time2.to_i).abs <= seconds_interval
|
|
228
|
-
end
|
|
229
|
-
|
|
230
279
|
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
require '
|
|
2
|
+
require 'test_helper'
|
|
3
3
|
require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class TestTimecopWithoutDate < Test::Unit::TestCase
|
|
6
6
|
|
|
7
7
|
def setup
|
|
8
8
|
assert !Object.const_defined?(:Date)
|
|
@@ -56,10 +56,10 @@ class TestTimecopWithouDate < 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 TestTimecopWithouDate < 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 TestTimecopWithouDate < 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 TestTimecopWithouDate < 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
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require "test/unit"
|
|
2
|
+
|
|
3
|
+
class TestTimecopWithoutDateButWithTime < Test::Unit::TestCase
|
|
4
|
+
TIMECOP_LIB = File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
|
|
5
|
+
|
|
6
|
+
def test_loads_properly_when_time_is_required_instead_of_date
|
|
7
|
+
assert_nothing_raised do
|
|
8
|
+
require "time"
|
|
9
|
+
require TIMECOP_LIB
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
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
|
+
version: 0.3.4
|
|
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-
|
|
12
|
+
date: 2009-12-07 00:00:00 -05:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|
|
@@ -23,19 +23,21 @@ 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
|
|
30
30
|
- VERSION.yml
|
|
31
31
|
- lib/timecop.rb
|
|
32
|
-
- lib/timecop/stack_item.rb
|
|
33
32
|
- lib/timecop/time_extensions.rb
|
|
33
|
+
- lib/timecop/time_stack_item.rb
|
|
34
34
|
- lib/timecop/timecop.rb
|
|
35
35
|
- test/run_tests.sh
|
|
36
|
+
- test/test_helper.rb
|
|
37
|
+
- test/test_time_stack_item.rb
|
|
36
38
|
- test/test_timecop.rb
|
|
37
|
-
- test/test_timecop_internals.rb
|
|
38
39
|
- test/test_timecop_without_date.rb
|
|
40
|
+
- test/test_timecop_without_date_but_with_time.rb
|
|
39
41
|
has_rdoc: true
|
|
40
42
|
homepage: http://github.com/jtrupiano/timecop
|
|
41
43
|
licenses: []
|
|
@@ -65,6 +67,8 @@ signing_key:
|
|
|
65
67
|
specification_version: 3
|
|
66
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.
|
|
67
69
|
test_files:
|
|
70
|
+
- test/test_helper.rb
|
|
71
|
+
- test/test_time_stack_item.rb
|
|
68
72
|
- test/test_timecop.rb
|
|
69
|
-
- test/test_timecop_internals.rb
|
|
70
73
|
- test/test_timecop_without_date.rb
|
|
74
|
+
- test/test_timecop_without_date_but_with_time.rb
|
data/lib/timecop/stack_item.rb
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
class Timecop
|
|
3
|
-
# Simply a data class for carrying around "time movement" objects. Makes it easy to keep track of the time
|
|
4
|
-
# movements on a simple stack.
|
|
5
|
-
class StackItem #:nodoc:
|
|
6
|
-
|
|
7
|
-
attr_reader :mock_type, :year, :month, :day, :hour, :minute, :second
|
|
8
|
-
def initialize(mock_type, year, month, day, hour, minute, second)
|
|
9
|
-
@mock_type, @year, @month, @day, @hour, @minute, @second = mock_type, year, month, day, hour, minute, second
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
require 'date'
|
|
3
|
-
require 'test/unit'
|
|
4
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
|
|
5
|
-
|
|
6
|
-
class TestTimecopInternals < Test::Unit::TestCase
|
|
7
|
-
|
|
8
|
-
def test_parse_travel_args_with_time
|
|
9
|
-
t = Time.now
|
|
10
|
-
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
|
11
|
-
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, t)
|
|
12
|
-
assert_equal y, ty
|
|
13
|
-
assert_equal m, tm
|
|
14
|
-
assert_equal d, td
|
|
15
|
-
assert_equal h, th
|
|
16
|
-
assert_equal min, tmin
|
|
17
|
-
assert_equal s, ts
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def test_parse_travel_args_with_datetime
|
|
21
|
-
t = DateTime.now
|
|
22
|
-
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
|
23
|
-
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, t)
|
|
24
|
-
assert_equal y, ty
|
|
25
|
-
assert_equal m, tm
|
|
26
|
-
assert_equal d, td
|
|
27
|
-
assert_equal h, th
|
|
28
|
-
assert_equal min, tmin
|
|
29
|
-
assert_equal s, ts
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def test_parse_travel_args_with_date
|
|
33
|
-
date = Date.today
|
|
34
|
-
y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0
|
|
35
|
-
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, date)
|
|
36
|
-
assert_equal y, ty
|
|
37
|
-
assert_equal m, tm
|
|
38
|
-
assert_equal d, td
|
|
39
|
-
assert_equal h, th
|
|
40
|
-
assert_equal min, tmin
|
|
41
|
-
assert_equal s, ts
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Due to the nature of this test (calling Time.now once in this test and
|
|
45
|
-
# once in #parse_travel_args), this test may fail when two subsequent calls
|
|
46
|
-
# to Time.now return a different second.
|
|
47
|
-
def test_parse_travel_args_with_integer
|
|
48
|
-
t = Time.now
|
|
49
|
-
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
|
50
|
-
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, 0)
|
|
51
|
-
assert_equal y, ty
|
|
52
|
-
assert_equal m, tm
|
|
53
|
-
assert_equal d, td
|
|
54
|
-
assert_equal h, th
|
|
55
|
-
assert_equal min, tmin
|
|
56
|
-
assert_equal s, ts
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def test_parse_travel_args_with_individual_arguments
|
|
60
|
-
y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10
|
|
61
|
-
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, y, m, d, h, min, s)
|
|
62
|
-
assert_equal y, ty
|
|
63
|
-
assert_equal m, tm
|
|
64
|
-
assert_equal d, td
|
|
65
|
-
assert_equal h, th
|
|
66
|
-
assert_equal min, tmin
|
|
67
|
-
assert_equal s, ts
|
|
68
|
-
end
|
|
69
|
-
end
|