timecop 0.3.5 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2008
3
+ Copyright (c) 2012 — Travis Jeffery, John Trupiano
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.markdown ADDED
@@ -0,0 +1,100 @@
1
+ # timecop
2
+
3
+ - Source[http://github.com/jtrupiano/timecop]
4
+ - Documentation[http://johntrupiano.rubyforge.org/timecop]
5
+
6
+ ## DESCRIPTION
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.
9
+
10
+ ## INSTALL
11
+
12
+ gem install timecop
13
+
14
+ ## FEATURES
15
+
16
+ - Freeze time to a specific point.
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
19
+ - Timecop api allows arguments to be passed into #freeze and #travel as one of the following:
20
+ - Time instance
21
+ - DateTime instance
22
+ - Date instance
23
+ - individual arguments (year, month, day, hour, minute, second)
24
+ - a single integer argument that is interpreted as an offset in seconds from Time.now
25
+ - Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now.
26
+ - Works with regular Ruby projects, and Ruby on Rails projects
27
+
28
+ ## USAGE
29
+
30
+ Run a time-sensitive test
31
+
32
+ ```ruby
33
+ joe = User.find(1)
34
+ joe.purchase_home()
35
+ assert !joe.mortgage_due?
36
+ # move ahead a month and assert that the mortgage is due
37
+ Timecop.freeze(Date.today + 30) do
38
+ assert joe.mortgage_due?
39
+ end
40
+ ```
41
+
42
+ Set the time for the test environment of a rails app -- this is particularly
43
+ helpful if your whole application is time-sensitive. It allows you to build
44
+ your test data at a single point in time, and to move in/out of that time as
45
+ appropriate (within your tests)
46
+
47
+ in config/environments/test.rb
48
+
49
+ ```ruby
50
+ config.after_initialize do
51
+ # Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward
52
+ t = Time.local(2008, 9, 1, 10, 5, 0)
53
+ Timecop.travel(t)
54
+ end
55
+ ```
56
+
57
+ ### The difference between Timecop.freeze and Timecop.travel
58
+
59
+ freeze is used to statically mock the concept of now. As your program executes,
60
+ Time.now will not change unless you make subsequent calls into the Timecop API.
61
+ travel, on the other hand, computes an offset between what we currently think
62
+ Time.now is (recall that we support nested traveling) and the time passed in.
63
+ It uses this offset to simulate the passage of time. To demonstrate, consider
64
+ the following code snippets:
65
+
66
+ ```ruby
67
+ new_time = Time.local(2008, 9, 1, 12, 0, 0)
68
+ Timecop.freeze(new_time)
69
+ sleep(10)
70
+ new_time == Time.now # ==> true
71
+
72
+ Timecop.return # "turn off" Timecop
73
+ Timecop.travel(new_time)
74
+ sleep(10)
75
+ new_time == Time.now # ==> false
76
+ ```
77
+
78
+ ## REFERENCES
79
+
80
+ * {0.3.4 release}[http://blog.smartlogicsolutions.com/2009/12/07/timecop-0-3-4-released/]
81
+ * {0.3.0 release}[http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/]
82
+ * {0.2.0 release}[http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/]
83
+ * {0.1.0 release}[http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/]
84
+
85
+ ## Contribute
86
+
87
+ timecop is maintained by [travisjeffery](http://github.com/travisjeffery), who
88
+ you can also hit up on [Twitter](http://twitter.com/travisjeffery).
89
+
90
+ Here's the most direct way to get your work merged into the project.
91
+
92
+ - Fork the project
93
+ - Clone down your fork
94
+ - Create a feature branch
95
+ - Hack away and add tests, not necessarily in that order
96
+ - Make sure everything still passes by running tests
97
+ - If necessary, rebase your commits into logical chunks without errors
98
+ - Push the branch up to your fork
99
+ - Send a pull request for your branch
100
+
data/Rakefile CHANGED
@@ -1,42 +1,10 @@
1
- require 'rake'
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
2
3
  require 'rake/testtask'
3
- require 'rake/rdoctask'
4
+ require 'rdoc/task'
4
5
 
5
- gem 'jeweler', '~> 1.3.0'
6
+ $LOAD_PATH.unshift("lib")
6
7
 
7
- begin
8
- require 'jeweler'
9
- Jeweler::Tasks.new do |s|
10
- s.name = "timecop"
11
- s.rubyforge_project = 'johntrupiano' # if different than lowercase project name
12
- s.description = %q(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.)
13
- s.summary = s.description # More details later??
14
- s.email = "jtrupiano@gmail.com"
15
- s.homepage = "http://github.com/jtrupiano/timecop"
16
- s.authors = ["John Trupiano"]
17
- s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"]
18
- end
19
- Jeweler::GemcutterTasks.new
20
- Jeweler::RubyforgeTasks.new do |rubyforge|
21
- rubyforge.doc_task = "rdoc"
22
- rubyforge.remote_doc_path = "timecop"
23
- end
24
- rescue LoadError
25
- puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
26
- end
27
-
28
- # Override the test task and instruct them how to actually run the tests.
29
- Rake.application.send(:eval, "@tasks.delete('test')")
30
- desc "Does not execute tests. Manually run shell script ./run_tests.sh to execute tests."
31
- task :test do
32
- puts <<-MSG
33
- In order to run the test suite, run: cd test && ./run_tests.sh
34
- The tests need to be run with different libraries loaded, which rules out using Rake
35
- to automate them.
36
- MSG
37
- end
38
-
39
- require 'rake/rdoctask'
40
8
  Rake::RDocTask.new do |rdoc|
41
9
  if File.exist?('VERSION')
42
10
  version = File.read('VERSION')
@@ -52,4 +20,9 @@ Rake::RDocTask.new do |rdoc|
52
20
  rdoc.rdoc_files.include('lib/**/*.rb')
53
21
  end
54
22
 
55
- task :default => :test
23
+ task :test do
24
+ system "cd test && ./run_tests.sh"
25
+ end
26
+
27
+ desc 'Default: run tests'
28
+ task :default => [:test]
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 5
2
+ :patch: 1
3
3
  :major: 0
4
- :minor: 3
4
+ :minor: 4
@@ -17,6 +17,7 @@ class Time #:nodoc:
17
17
 
18
18
  # Alias now to now_with_mock_time
19
19
  alias_method :now, :now_with_mock_time
20
+ alias_method :new, :now
20
21
  end
21
22
  end
22
23
 
@@ -69,4 +70,4 @@ if Object.const_defined?(:DateTime) && DateTime.respond_to?(:now)
69
70
  alias_method :now, :now_with_mock_time
70
71
  end
71
72
  end
72
- end
73
+ end
@@ -10,7 +10,7 @@ class Timecop
10
10
  @mock_type = mock_type
11
11
  @time = parse_time(*args)
12
12
  @travel_offset = compute_travel_offset
13
- @dst_adjustment = compute_dst_adjustment
13
+ @dst_adjustment = compute_dst_adjustment(@time)
14
14
  end
15
15
 
16
16
  def year
@@ -60,7 +60,9 @@ class Timecop
60
60
  def datetime
61
61
  # DateTime doesn't know about DST, so let's remove its presence
62
62
  our_offset = utc_offset + dst_adjustment
63
- DateTime.new(year, month, day, hour, min, sec, utc_offset_to_rational(our_offset))
63
+ fractions_of_a_second = time.to_f % 1
64
+ DateTime.new(year, month, day, hour, min, sec + fractions_of_a_second,
65
+ utc_offset_to_rational(our_offset))
64
66
  end
65
67
 
66
68
  def dst_adjustment
@@ -77,28 +79,42 @@ class Timecop
77
79
  end
78
80
 
79
81
  def parse_time(*args)
82
+ time_klass = Time
83
+ time_klass = Time.zone if Time.respond_to? :zone
80
84
  arg = args.shift
81
85
  if arg.is_a?(Time)
82
- arg.getlocal
86
+ if arg.respond_to?(:in_time_zone)
87
+ arg.in_time_zone
88
+ else
89
+ arg.getlocal
90
+ end
83
91
  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
92
+ expected_time = time_klass.local(arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec)
93
+ expected_time += expected_time.utc_offset - rational_to_utc_offset(arg.offset)
94
+ expected_time + compute_dst_adjustment(expected_time)
86
95
  elsif Object.const_defined?(:Date) && arg.is_a?(Date)
87
- Time.local(arg.year, arg.month, arg.day, 0, 0, 0)
96
+ time_klass.local(arg.year, arg.month, arg.day, 0, 0, 0)
88
97
  elsif args.empty? && arg.kind_of?(Integer)
89
98
  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)
99
+ elsif arg.nil?
100
+ Time.now
101
+ else
102
+ if Time.respond_to?(:parse)
103
+ Time.parse(arg)
104
+ else
105
+ # we'll just assume it's a list of y/m/d/h/m/s
106
+ year = arg || 2000
107
+ month = args.shift || 1
108
+ day = args.shift || 1
109
+ hour = args.shift || 0
110
+ minute = args.shift || 0
111
+ second = args.shift || 0
112
+ time_klass.local(year, month, day, hour, minute, second)
113
+ end
98
114
  end
99
115
  end
100
116
 
101
- def compute_dst_adjustment
117
+ def compute_dst_adjustment(time)
102
118
  return 0 if !(time.dst? ^ Time.now.dst?)
103
119
  return -1 * 60 * 60 if time.dst?
104
120
  return 60 * 60
@@ -6,13 +6,13 @@ require 'timecop/time_stack_item'
6
6
  # * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects
7
7
  # * Allows us to "freeze" time in our Ruby applications.
8
8
  # * Optionally allows time travel to simulate a running clock, such time is not technically frozen.
9
- #
10
- # This is very useful when your app's functionality is dependent on time (e.g.
9
+ #
10
+ # This is very useful when your app's functionality is dependent on time (e.g.
11
11
  # anything that might expire). This will allow us to alter the return value of
12
12
  # Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change.
13
13
  class Timecop
14
14
  include Singleton
15
-
15
+
16
16
  # Allows you to run a block of code and "fake" a time throughout the execution of that block.
17
17
  # This is particularly useful for writing test methods where the passage of time is critical to the business
18
18
  # logic being tested. For example:
@@ -32,16 +32,16 @@ class Timecop
32
32
  # 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0)
33
33
  #
34
34
  # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their
35
- # previous values after the block has finished executing. This allows us to nest multiple
35
+ # previous values after the block has finished executing. This allows us to nest multiple
36
36
  # calls to Timecop.travel and have each block maintain it's concept of "now."
37
37
  #
38
38
  # * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if
39
39
  # benchmark or other timing calls are executed, which implicitly expect Time to actually move
40
40
  # forward.
41
41
  #
42
- # * Rails Users: Be especially careful when setting this in your development environment in a
43
- # rails project. Generators will load your environment, including the migration generator,
44
- # which will lead to files being generated with the timestamp set by the Timecop.freeze call
42
+ # * Rails Users: Be especially careful when setting this in your development environment in a
43
+ # rails project. Generators will load your environment, including the migration generator,
44
+ # which will lead to files being generated with the timestamp set by the Timecop.freeze call
45
45
  # in your dev environment
46
46
  #
47
47
  # Returns the frozen time.
@@ -49,7 +49,7 @@ class Timecop
49
49
  instance().send(:travel, :freeze, *args, &block)
50
50
  Time.now
51
51
  end
52
-
52
+
53
53
  # Allows you to run a block of code and "fake" a time throughout the execution of that block.
54
54
  # See Timecop#freeze for a sample of how to use (same exact usage syntax)
55
55
  #
@@ -61,7 +61,15 @@ class Timecop
61
61
  instance().send(:travel, :travel, *args, &block)
62
62
  Time.now
63
63
  end
64
-
64
+
65
+ def self.baseline
66
+ instance().send(:baseline)
67
+ end
68
+
69
+ def self.baseline=(baseline)
70
+ instance().send(:baseline=, baseline)
71
+ end
72
+
65
73
  # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists).
66
74
  #
67
75
  # Returns Time.now, which is now the real current time.
@@ -69,35 +77,53 @@ class Timecop
69
77
  instance().send(:unmock!)
70
78
  Time.now
71
79
  end
72
-
80
+
81
+ def self.return_to_baseline
82
+ instance().send(:return_to_baseline)
83
+ Time.now
84
+ end
85
+
73
86
  def self.top_stack_item #:nodoc:
74
87
  instance().instance_variable_get(:@_stack).last
75
88
  end
76
89
 
77
90
  protected
78
-
91
+
92
+ def baseline=(baseline)
93
+ @baseline = baseline
94
+ @_stack << TimeStackItem.new(:travel, baseline)
95
+ end
96
+
79
97
  def initialize #:nodoc:
80
98
  @_stack = []
81
99
  end
82
-
100
+
83
101
  def travel(mock_type, *args, &block) #:nodoc:
84
102
  stack_item = TimeStackItem.new(mock_type, *args)
85
-
103
+
86
104
  # store this time traveling on our stack...
87
105
  @_stack << stack_item
88
-
106
+
89
107
  if block_given?
90
108
  begin
91
- yield
109
+ yield stack_item.time
92
110
  ensure
93
111
  # pull it off the stack...
94
112
  @_stack.pop
95
113
  end
96
114
  end
97
115
  end
98
-
116
+
99
117
  def unmock! #:nodoc:
118
+ @baseline = nil
100
119
  @_stack = []
101
120
  end
102
-
121
+
122
+ def return_to_baseline
123
+ if @baseline
124
+ @_stack = [@_stack.shift]
125
+ else
126
+ unmock!
127
+ end
128
+ end
103
129
  end
data/test/run_tests.sh CHANGED
@@ -1,13 +1,6 @@
1
1
  #!/bin/sh
2
2
 
3
- echo "\033[1;81m Running test_time_stack_item...\033[0m"
4
- ruby -I../lib test_time_stack_item.rb || (echo "FAILED!!!!!!!!!!!!")
3
+ for f in *_test.rb; do
4
+ ${RUBY:-ruby} -I../lib:. $f
5
+ done
5
6
 
6
- echo "\033[1;81m Running test_timecop_without_date...\033[0m"
7
- ruby -I../lib test_timecop_without_date.rb || (echo "FAILED!!!!!!!!!!!!")
8
-
9
- echo "\033[1;81m Running test_timecop_without_date_but_with_time...\033[0m"
10
- ruby -I../lib test_timecop_without_date_but_with_time.rb || (echo "FAILED!!!!!!!!!!!!")
11
-
12
- echo "\033[1;81m Running test_timecop...\033[0m"
13
- ruby -I../lib test_timecop.rb || (echo "FAILED!!!!!!!!!!!!")
data/test/test_helper.rb CHANGED
@@ -1,6 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
1
3
  require 'test/unit'
4
+ require 'mocha'
2
5
 
3
6
  class Test::Unit::TestCase
7
+
4
8
  private
5
9
  # Tests to see that two times are within the given distance,
6
10
  # in seconds, from each other.
@@ -43,4 +47,4 @@ class Test::Unit::TestCase
43
47
  assert_equal dt1, dt2, "Failed for timezone: #{ENV['TZ']}: #{dt1.to_s} not equal to #{dt2.to_s}"
44
48
  end
45
49
 
46
- end
50
+ end
@@ -97,8 +97,7 @@ class TestTimeStackItem < Test::Unit::TestCase
97
97
  Timecop.freeze(DateTime.parse("2009-10-1 00:38:00 -0400"))
98
98
  t = DateTime.parse("2009-10-11 00:00:00 -0400")
99
99
  tsi = Timecop::TimeStackItem.new(:freeze, t)
100
- assert Time.now.dst?, "precondition"
101
- assert tsi.time.dst?, "precondition"
100
+ return if !(Time.now.dst? && tsi.time.dst?)
102
101
  assert_equal 0, tsi.send(:dst_adjustment)
103
102
  end
104
103
 
@@ -106,8 +105,7 @@ class TestTimeStackItem < Test::Unit::TestCase
106
105
  Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0400"))
107
106
  t = DateTime.parse("2009-12-11 00:00:00 -0400")
108
107
  tsi = Timecop::TimeStackItem.new(:freeze, t)
109
- assert !Time.now.dst?, "precondition"
110
- assert !tsi.time.dst?, "precondition"
108
+ return if Time.now.dst? || tsi.time.dst?
111
109
  assert_equal 0, tsi.send(:dst_adjustment)
112
110
  end
113
111
 
@@ -115,8 +113,7 @@ class TestTimeStackItem < Test::Unit::TestCase
115
113
  Timecop.freeze(DateTime.parse("2009-10-1 00:38:00 -0400"))
116
114
  t = DateTime.parse("2009-12-11 00:00:00 -0400")
117
115
  tsi = Timecop::TimeStackItem.new(:freeze, t)
118
- assert Time.now.dst?, "precondition"
119
- assert !tsi.time.dst?, "precondition"
116
+ return if !Time.now.dst? || tsi.time.dst?
120
117
  assert_equal 60 * 60, tsi.send(:dst_adjustment)
121
118
  end
122
119
 
@@ -124,27 +121,24 @@ class TestTimeStackItem < Test::Unit::TestCase
124
121
  Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0400"))
125
122
  t = DateTime.parse("2009-10-11 00:00:00 -0400")
126
123
  tsi = Timecop::TimeStackItem.new(:freeze, t)
127
- assert !Time.now.dst?, "precondition"
128
- assert tsi.time.dst?, "precondition"
124
+ return if Time.now.dst? || !tsi.time.dst?
129
125
  assert_equal -1 * 60 * 60, tsi.send(:dst_adjustment)
130
126
  end
131
127
 
132
- # Ensure DateTime's handle changing DST properly
128
+ # Ensure DateTimes handle changing DST properly
133
129
  def test_datetime_for_dst_to_non_dst
134
130
  Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500"))
135
131
  t = DateTime.parse("2009-10-11 00:00:00 -0400")
136
132
  tsi = Timecop::TimeStackItem.new(:freeze, t)
137
133
  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
134
  end
141
135
 
142
136
  def test_datetime_for_non_dst_to_dst
143
137
  Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 -0400"))
144
138
  t = DateTime.parse("2009-11-30 23:38:00 -0500")
145
139
  tsi = Timecop::TimeStackItem.new(:freeze, t)
140
+ return if !tsi.time.dst?
146
141
  assert_date_times_equal t, tsi.datetime
147
- # verify Date also 'moves forward' an hour to change the day
148
142
  assert_equal Date.new(2009, 12, 1), tsi.date
149
143
  end
150
144
 
@@ -164,4 +158,26 @@ class TestTimeStackItem < Test::Unit::TestCase
164
158
  tsi = Timecop::TimeStackItem.new(:freeze, t)
165
159
  assert_equal nil, tsi.send(:travel_offset)
166
160
  end
167
- end
161
+
162
+ def test_parse_string_date_with_active_support
163
+ date = '2012-01-02'
164
+ Time.expects(:parse).with(date).returns(Time.local(2012, 01, 02))
165
+ Timecop.freeze(date)
166
+ end
167
+
168
+ def test_integration_with_rails_time_zone
169
+ time = Time.now
170
+ def time.in_time_zone
171
+ self - 3600
172
+ end
173
+ t = time - 3600
174
+ stack_item = Timecop::TimeStackItem.new(:freeze, time)
175
+ y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
176
+ assert_equal y, stack_item.year
177
+ assert_equal m, stack_item.month
178
+ assert_equal d, stack_item.day
179
+ assert_equal h, stack_item.hour
180
+ assert_equal min, stack_item.min
181
+ assert_equal s, stack_item.sec
182
+ end
183
+ end
@@ -3,20 +3,20 @@ require 'test_helper'
3
3
  require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
4
4
 
5
5
  class TestTimecop < Test::Unit::TestCase
6
-
6
+
7
7
  def setup
8
-
8
+
9
9
  end
10
-
10
+
11
11
  # just in case...let's really make sure that Timecop is disabled between tests...
12
12
  def teardown
13
13
  Timecop.return
14
14
  end
15
-
15
+
16
16
  def test_freeze_changes_and_resets_time
17
17
  # depending on how we're invoked (individually or via the rake test suite)
18
18
  assert !Time.respond_to?(:zone) || Time.zone.nil?
19
-
19
+
20
20
  t = Time.local(2008, 10, 10, 10, 10, 10)
21
21
  assert_not_equal t, Time.now
22
22
  Timecop.freeze(2008, 10, 10, 10, 10, 10) do
@@ -24,6 +24,12 @@ class TestTimecop < Test::Unit::TestCase
24
24
  end
25
25
  assert_not_equal t, Time.now
26
26
  end
27
+
28
+ def test_freeze_yields_mocked_time
29
+ Timecop.freeze(2008, 10, 10, 10, 10, 10) do |frozen_time|
30
+ assert_equal frozen_time, Time.now
31
+ end
32
+ end
27
33
 
28
34
  def test_freeze_then_return_unsets_mock_time
29
35
  Timecop.freeze(1)
@@ -36,22 +42,27 @@ class TestTimecop < Test::Unit::TestCase
36
42
  Timecop.return
37
43
  assert_nil Time.send(:mock_time)
38
44
  end
39
-
45
+
40
46
  def test_freeze_with_block_unsets_mock_time
41
47
  assert_nil Time.send(:mock_time), "test is invalid"
42
48
  Timecop.freeze(1) do; end
43
49
  assert_nil Time.send(:mock_time)
44
50
  end
45
-
51
+
46
52
  def test_travel_with_block_unsets_mock_time
47
53
  assert_nil Time.send(:mock_time), "test is invalid"
48
54
  Timecop.travel(1) do; end
49
55
  assert_nil Time.send(:mock_time)
50
56
  end
51
-
57
+
58
+ def test_travel_does_not_reduce_precision_of_datetime
59
+ Timecop.travel(1)
60
+ assert_not_equal DateTime.now, DateTime.now
61
+ end
62
+
52
63
  def test_recursive_freeze
53
64
  t = Time.local(2008, 10, 10, 10, 10, 10)
54
- Timecop.freeze(2008, 10, 10, 10, 10, 10) do
65
+ Timecop.freeze(2008, 10, 10, 10, 10, 10) do
55
66
  assert_equal t, Time.now
56
67
  t2 = Time.local(2008, 9, 9, 9, 9, 9)
57
68
  Timecop.freeze(2008, 9, 9, 9, 9, 9) do
@@ -61,10 +72,10 @@ class TestTimecop < Test::Unit::TestCase
61
72
  end
62
73
  assert_not_equal t, Time.now
63
74
  end
64
-
75
+
65
76
  def test_freeze_with_time_instance_works_as_expected
66
77
  t = Time.local(2008, 10, 10, 10, 10, 10)
67
- Timecop.freeze(t) do
78
+ Timecop.freeze(t) do
68
79
  assert_equal t, Time.now
69
80
  assert_date_times_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
70
81
  assert_equal Date.new(2008, 10, 10), Date.today
@@ -73,7 +84,7 @@ class TestTimecop < Test::Unit::TestCase
73
84
  assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now
74
85
  assert_not_equal Date.new(2008, 10, 10), Date.today
75
86
  end
76
-
87
+
77
88
  def test_freeze_with_datetime_on_specific_timezone_during_dst
78
89
  each_timezone do
79
90
  # Start from a time that is subject to DST
@@ -87,7 +98,7 @@ class TestTimecop < Test::Unit::TestCase
87
98
  Timecop.return
88
99
  end
89
100
  end
90
-
101
+
91
102
  def test_freeze_with_datetime_on_specific_timezone_not_during_dst
92
103
  each_timezone do
93
104
  # Start from a time that is not subject to DST
@@ -99,7 +110,7 @@ class TestTimecop < Test::Unit::TestCase
99
110
  end
100
111
  end
101
112
  end
102
-
113
+
103
114
  def test_freeze_with_datetime_from_a_non_dst_time_to_a_dst_time
104
115
  each_timezone do
105
116
  # Start from a time that is not subject to DST
@@ -109,7 +120,7 @@ class TestTimecop < Test::Unit::TestCase
109
120
  Timecop.freeze(t) do
110
121
  assert_date_times_equal t, DateTime.now
111
122
  end
112
- end
123
+ end
113
124
  end
114
125
 
115
126
  def test_freeze_with_datetime_from_a_dst_time_to_a_non_dst_time
@@ -121,9 +132,9 @@ class TestTimecop < Test::Unit::TestCase
121
132
  Timecop.freeze(t) do
122
133
  assert_date_times_equal t, DateTime.now
123
134
  end
124
- end
135
+ end
125
136
  end
126
-
137
+
127
138
  def test_freeze_with_date_instance_works_as_expected
128
139
  d = Date.new(2008, 10, 10)
129
140
  Timecop.freeze(d) do
@@ -133,9 +144,9 @@ class TestTimecop < Test::Unit::TestCase
133
144
  end
134
145
  assert_not_equal d, Date.today
135
146
  assert_not_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now
136
- assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now
147
+ assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now
137
148
  end
138
-
149
+
139
150
  def test_freeze_with_integer_instance_works_as_expected
140
151
  t = Time.local(2008, 10, 10, 10, 10, 10)
141
152
  Timecop.freeze(t) do
@@ -165,7 +176,7 @@ class TestTimecop < Test::Unit::TestCase
165
176
  assert_nil Time.send(:mock_time)
166
177
  end
167
178
  end
168
-
179
+
169
180
  def test_freeze_freezes_time
170
181
  t = Time.local(2008, 10, 10, 10, 10, 10)
171
182
  now = Time.now
@@ -179,7 +190,7 @@ class TestTimecop < Test::Unit::TestCase
179
190
  assert_equal new_dt, DateTime.now
180
191
  end
181
192
  end
182
-
193
+
183
194
  def test_travel_keeps_time_moving
184
195
  t = Time.local(2008, 10, 10, 10, 10, 10)
185
196
  now = Time.now
@@ -190,7 +201,7 @@ class TestTimecop < Test::Unit::TestCase
190
201
  assert_times_effectively_not_equal new_now, Time.now, 0.25, "Looks like time is not moving"
191
202
  end
192
203
  end
193
-
204
+
194
205
  def test_mocked_date_time_now_is_local
195
206
  each_timezone do
196
207
  t = DateTime.parse("2009-10-11 00:38:00 +0200")
@@ -199,7 +210,7 @@ class TestTimecop < Test::Unit::TestCase
199
210
  end
200
211
  end
201
212
  end
202
-
213
+
203
214
  def test_freeze_with_utc_time
204
215
  each_timezone do
205
216
  t = Time.utc(2008, 10, 10, 10, 10, 10)
@@ -224,10 +235,10 @@ class TestTimecop < Test::Unit::TestCase
224
235
  assert !Time.now.utc?, "Failed to thwart destructive methods."
225
236
  end
226
237
  end
227
-
238
+
228
239
  def test_recursive_travel_maintains_each_context
229
240
  t = Time.local(2008, 10, 10, 10, 10, 10)
230
- Timecop.travel(2008, 10, 10, 10, 10, 10) do
241
+ Timecop.travel(2008, 10, 10, 10, 10, 10) do
231
242
  assert((t - Time.now).abs < 50, "Failed to travel time.")
232
243
  t2 = Time.local(2008, 9, 9, 9, 9, 9)
233
244
  Timecop.travel(2008, 9, 9, 9, 9, 9) do
@@ -238,10 +249,18 @@ class TestTimecop < Test::Unit::TestCase
238
249
  end
239
250
  assert_nil Time.send(:mock_time)
240
251
  end
252
+
253
+ def test_recursive_travel_yields_correct_time
254
+ Timecop.travel(2008, 10, 10, 10, 10, 10) do
255
+ Timecop.travel(2008, 9, 9, 9, 9, 9) do |inner_freeze|
256
+ assert_times_effectively_equal inner_freeze, Time.now, 1, "Failed to yield current time back to block"
257
+ end
258
+ end
259
+ end
241
260
 
242
261
  def test_recursive_travel_then_freeze
243
262
  t = Time.local(2008, 10, 10, 10, 10, 10)
244
- Timecop.travel(2008, 10, 10, 10, 10, 10) do
263
+ Timecop.travel(2008, 10, 10, 10, 10, 10) do
245
264
  assert((t - Time.now).abs < 50, "Failed to travel time.")
246
265
  t2 = Time.local(2008, 9, 9, 9, 9, 9)
247
266
  Timecop.freeze(2008, 9, 9, 9, 9, 9) do
@@ -251,10 +270,10 @@ class TestTimecop < Test::Unit::TestCase
251
270
  end
252
271
  assert_nil Time.send(:mock_time)
253
272
  end
254
-
273
+
255
274
  def test_recursive_freeze_then_travel
256
275
  t = Time.local(2008, 10, 10, 10, 10, 10)
257
- Timecop.freeze(t) do
276
+ Timecop.freeze(t) do
258
277
  assert_equal t, Time.now
259
278
  t2 = Time.local(2008, 9, 9, 9, 9, 9)
260
279
  Timecop.travel(t2) do
@@ -263,27 +282,27 @@ class TestTimecop < Test::Unit::TestCase
263
282
  end
264
283
  assert_equal t, Time.now
265
284
  end
266
- assert_nil Time.send(:mock_time)
285
+ assert_nil Time.send(:mock_time)
267
286
  end
268
-
287
+
269
288
  def test_return_values_are_Time_instances
270
289
  assert Timecop.freeze.is_a?(Time)
271
290
  assert Timecop.travel.is_a?(Time)
272
291
  assert Timecop.return.is_a?(Time)
273
292
  end
274
-
293
+
275
294
  def test_travel_time_returns_passed_value
276
295
  t_future = Time.local(2030, 10, 10, 10, 10, 10)
277
296
  t_travel = Timecop.travel t_future
278
297
  assert times_effectively_equal(t_future, t_travel)
279
298
  end
280
-
299
+
281
300
  def test_freeze_time_returns_passed_value
282
301
  t_future = Time.local(2030, 10, 10, 10, 10, 10)
283
302
  t_frozen = Timecop.freeze t_future
284
303
  assert times_effectively_equal(t_future, t_frozen)
285
304
  end
286
-
305
+
287
306
  def test_return_time_returns_actual_time
288
307
  t_real = Time.now
289
308
  Timecop.freeze Time.local(2030, 10, 10, 10, 10, 10)
@@ -291,4 +310,46 @@ class TestTimecop < Test::Unit::TestCase
291
310
  assert times_effectively_equal(t_real, t_return)
292
311
  end
293
312
 
294
- end
313
+ def test_freeze_without_params
314
+ Timecop.freeze 1 do
315
+ current_time = Time.now
316
+ Timecop.freeze do
317
+ assert_equal Time.now, current_time
318
+ end
319
+ end
320
+ end
321
+
322
+ def test_return_to_baseline_without_a_baseline_set_returns_to_current_time
323
+ time_before_travel = Time.now
324
+ Timecop.travel Time.now - 60
325
+ Timecop.return_to_baseline
326
+ assert times_effectively_equal(time_before_travel, Time.now)
327
+ end
328
+
329
+ def test_return_to_baseline_with_a_baseline_set_returns_to_baseline
330
+ baseline = Time.local(1945, 10, 10, 10, 10, 10)
331
+ Timecop.baseline = baseline
332
+ Timecop.travel Time.now - 60
333
+ time_now = Timecop.return_to_baseline
334
+ assert times_effectively_equal(baseline, time_now),
335
+ "expected to return to #{baseline}, but returned to #{time_now}"
336
+ end
337
+
338
+ def test_return_eliminates_baseline
339
+ time_before_travel = Time.now
340
+ Timecop.baseline = Time.local(1937, 9, 9, 9, 9, 9)
341
+ Timecop.return
342
+ assert times_effectively_equal(time_before_travel, Time.now)
343
+
344
+ Timecop.travel(Time.now - 100)
345
+ Timecop.return_to_baseline
346
+ assert times_effectively_equal(time_before_travel, Time.now)
347
+ end
348
+
349
+ def test_mock_time_new_same_as_now
350
+ date = Time.local(2011, 01, 02)
351
+ Timecop.freeze date
352
+ assert_equal date, Time.now
353
+ assert_equal date, Time.new
354
+ end
355
+ end
@@ -5,8 +5,8 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
5
5
  class TestTimecopWithoutDate < Test::Unit::TestCase
6
6
 
7
7
  def setup
8
- assert !Object.const_defined?(:Date)
9
- assert !Object.const_defined?(:DateTime)
8
+ Object.send(:remove_const, :Date) if Object.const_defined?(:Date)
9
+ Object.send(:remove_const, :DateTime) if Object.const_defined?(:DateTime)
10
10
  end
11
11
 
12
12
  # just in case...let's really make sure that Timecop is disabled between tests...
@@ -116,4 +116,4 @@ class TestTimecopWithoutDate < Test::Unit::TestCase
116
116
  assert_nil Time.send(:mock_time)
117
117
  end
118
118
 
119
- end
119
+ end
metadata CHANGED
@@ -1,37 +1,30 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: timecop
3
- version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 3
9
- - 5
10
- version: 0.3.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.1
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
8
+ - Travis Jeffery
13
9
  - John Trupiano
14
10
  autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
-
18
- date: 2010-06-07 00:00:00 -04:00
19
- default_executable:
13
+ date: 2012-06-27 00:00:00.000000000Z
20
14
  dependencies: []
21
-
22
- description: 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.
23
- email: jtrupiano@gmail.com
15
+ description: A gem providing "time travel" and "time freezing" capabilities, making
16
+ it dead simple to test time-dependent code. It provides a unified method to mock
17
+ Time.now, Date.today, and DateTime.now in a single call.
18
+ email: travisjeffery@gmail.com
24
19
  executables: []
25
-
26
20
  extensions: []
27
-
28
- extra_rdoc_files:
21
+ extra_rdoc_files:
29
22
  - LICENSE
30
- - README.rdoc
31
- files:
23
+ - README.markdown
24
+ files:
32
25
  - History.rdoc
33
26
  - LICENSE
34
- - README.rdoc
27
+ - README.markdown
35
28
  - Rakefile
36
29
  - VERSION.yml
37
30
  - lib/timecop.rb
@@ -40,47 +33,40 @@ files:
40
33
  - lib/timecop/timecop.rb
41
34
  - test/run_tests.sh
42
35
  - test/test_helper.rb
43
- - test/test_time_stack_item.rb
44
- - test/test_timecop.rb
45
- - test/test_timecop_without_date.rb
46
- - test/test_timecop_without_date_but_with_time.rb
47
- has_rdoc: true
36
+ - test/time_stack_item_test.rb
37
+ - test/timecop_test.rb
38
+ - test/timecop_without_date_test.rb
39
+ - test/timecop_without_date_but_with_time_test.rb
48
40
  homepage: http://github.com/jtrupiano/timecop
49
41
  licenses: []
50
-
51
42
  post_install_message:
52
- rdoc_options:
43
+ rdoc_options:
53
44
  - --charset=UTF-8
54
- require_paths:
45
+ require_paths:
55
46
  - lib
56
- required_ruby_version: !ruby/object:Gem::Requirement
47
+ required_ruby_version: !ruby/object:Gem::Requirement
57
48
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
- version: "0"
65
- required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
54
  none: false
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 3
71
- segments:
72
- - 0
73
- version: "0"
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
74
59
  requirements: []
75
-
76
60
  rubyforge_project: johntrupiano
77
- rubygems_version: 1.3.7
61
+ rubygems_version: 1.8.10
78
62
  signing_key:
79
63
  specification_version: 3
80
- 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.
81
- test_files:
64
+ summary: A gem providing "time travel" and "time freezing" capabilities, making it
65
+ dead simple to test time-dependent code. It provides a unified method to mock Time.now,
66
+ Date.today, and DateTime.now in a single call.
67
+ test_files:
82
68
  - test/test_helper.rb
83
- - test/test_time_stack_item.rb
84
- - test/test_timecop.rb
85
- - test/test_timecop_without_date.rb
86
- - test/test_timecop_without_date_but_with_time.rb
69
+ - test/time_stack_item_test.rb
70
+ - test/timecop_test.rb
71
+ - test/timecop_without_date_test.rb
72
+ - test/timecop_without_date_but_with_time_test.rb
data/README.rdoc DELETED
@@ -1,68 +0,0 @@
1
- = timecop
2
-
3
- * Source[http://github.com/jtrupiano/timecop]
4
- * Documentation[http://johntrupiano.rubyforge.org/timecop]
5
-
6
- == DESCRIPTION
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.
9
-
10
- == INSTALL
11
-
12
- gem install timecop
13
-
14
- == FEATURES
15
-
16
- * Freeze time to a specific point.
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
19
- * Timecop api allows arguments to be passed into #freeze and #travel as one of the following:
20
- * Time instance
21
- * DateTime instance
22
- * Date instance
23
- * individual arguments (year, month, day, hour, minute, second)
24
- * a single integer argument that is interpreted as an offset in seconds from Time.now
25
- * Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now.
26
-
27
- == USAGE
28
-
29
- Run a time-sensitive test
30
-
31
- joe = User.find(1)
32
- joe.purchase_home()
33
- assert !joe.mortgage_due?
34
- # move ahead a month and assert that the mortgage is due
35
- Timecop.freeze(Date.today + 30) do
36
- assert joe.mortgage_due?
37
- end
38
-
39
- Set the time for the test environment of a rails app -- this is particularly helpful if your whole application is time-sensitive. It allows you to build your test data at a single point in time, and to move in/out of that time as appropriate (within your tests)
40
-
41
- in config/environments/test.rb
42
-
43
- config.after_initialize do
44
- # Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward
45
- t = Time.local(2008, 9, 1, 10, 5, 0)
46
- Timecop.travel(t)
47
- end
48
-
49
- === The difference between Timecop.freeze and Timecop.travel
50
-
51
- #freeze is used to statically mock the concept of now. As your program executes, Time.now will not change unless you make subsequent calls into the Timecop API. #travel, on the other hand, computes an offset between what we currently think Time.now is (recall that we support nested traveling) and the time passed in. It uses this offset to simulate the passage of time. To demonstrate, consider the following code snippets:
52
-
53
- new_time = Time.local(2008, 9, 1, 12, 0, 0)
54
- Timecop.freeze(new_time)
55
- sleep(10)
56
- new_time == Time.now # ==> true
57
-
58
- Timecop.return # "turn off" Timecop
59
- Timecop.travel(new_time)
60
- sleep(10)
61
- new_time == Time.now # ==> false
62
-
63
- == REFERENCES
64
-
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/]