timecop-0.9.1/0000755000004100000410000000000013312111520013176 5ustar www-datawww-datatimecop-0.9.1/test/0000755000004100000410000000000013312111520014155 5ustar www-datawww-datatimecop-0.9.1/test/time_stack_item_test.rb0000644000004100000410000002207613312111520020711 0ustar www-datawww-datarequire 'date' require_relative "test_helper" require 'timecop' require 'active_support/all' class TestTimeStackItem < Minitest::Test def teardown Timecop.return Time.zone = nil end def test_new_with_time t = Time.now y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, t) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_time_and_arguments t = Time.new(2012, 7, 28, 20, 0) y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, t) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_datetime_now t = DateTime.now y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, t) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_datetime_in_different_timezone each_timezone do t = DateTime.parse("2009-10-11 00:38:00 +0200") stack_item = Timecop::TimeStackItem.new(:freeze, t) assert_date_times_equal(t, stack_item.datetime) end end def test_new_with_date date = Date.today y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0 stack_item = Timecop::TimeStackItem.new(:freeze, date) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end # Due to the nature of this test (calling Time.now once in this test and # once in #new), this test may fail when two subsequent calls # to Time.now return a different second. def test_new_with_integer t = Time.now y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, 0) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_float t = Time.now y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, 0.0) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_individual_arguments y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10 stack_item = Timecop::TimeStackItem.new(:freeze, y, m, d, h, min, s) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_rational_to_utc_offset assert_equal -14400, a_time_stack_item.send(:rational_to_utc_offset, Rational(-1, 6)) assert_equal -18000, a_time_stack_item.send(:rational_to_utc_offset, Rational(-5, 24)) assert_equal 0, a_time_stack_item.send(:rational_to_utc_offset, Rational(0, 1)) assert_equal 3600, a_time_stack_item.send(:rational_to_utc_offset, Rational(1, 24)) end def test_utc_offset_to_rational assert_equal Rational(-1, 6), a_time_stack_item.send(:utc_offset_to_rational, -14400) assert_equal Rational(-5, 24), a_time_stack_item.send(:utc_offset_to_rational, -18000) assert_equal Rational(0, 1), a_time_stack_item.send(:utc_offset_to_rational, 0) assert_equal Rational(1, 24), a_time_stack_item.send(:utc_offset_to_rational, 3600) end def test_datetime_in_presence_of_activesupport_timezone skip('requires ActiveSupport') unless Time.respond_to? :zone backed_up_zone, backed_up_tzvar = Time.zone, ENV['TZ'] Time.zone = ENV['TZ'] = 'America/Los_Angeles' t = DateTime.new(2001, 2, 28, 23, 59, 59.5) tsi = Timecop::TimeStackItem.new(:freeze, t) assert_date_times_equal t, tsi.datetime ensure Time.zone, ENV['TZ'] = backed_up_zone, backed_up_tzvar end # Ensure DateTimes handle changing DST properly def test_datetime_for_dst_to_non_dst Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500")) t = DateTime.parse("2009-10-11 00:00:00 -0400") tsi = Timecop::TimeStackItem.new(:freeze, t) assert_date_times_equal t, tsi.datetime end # Ensure DateTimes handle changing DST properly when changing from DateTime to Time def test_datetime_for_dst_to_time_for_non_dst Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500")) t = DateTime.parse("2009-10-11 00:00:00 -0400") tsi = Timecop::TimeStackItem.new(:freeze, t) assert_date_times_equal t.to_time, tsi.time end def test_datetime_for_non_dst_to_dst Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 -0400")) t = DateTime.parse("2009-11-30 23:38:00 -0500") tsi = Timecop::TimeStackItem.new(:freeze, t) return if !tsi.time.dst? assert_date_times_equal t, tsi.datetime assert_equal Date.new(2009, 12, 1), tsi.date end def test_set_travel_offset_for_travel t_now = Time.now t = Time.local(2009, 10, 1, 0, 0, 30) expected_offset = t - t_now tsi = Timecop::TimeStackItem.new(:travel, t) assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly" end def test_set_travel_offset_for_freeze Timecop.freeze(2009, 10, 1, 0, 0, 0) t = Time.local(2009, 10, 1, 0, 0, 30) tsi = Timecop::TimeStackItem.new(:freeze, t) assert_equal nil, tsi.send(:travel_offset) end def test_timezones Time.zone = "Europe/Zurich" time = Time.zone.parse("2012-12-27T12:12:12+08:00") Timecop.freeze(time) do |frozen_time| assert_equal time, frozen_time end end def test_timezones_with_parsed_string Time.zone = "Europe/Zurich" time_string = "2012-12-27 12:12" expected_time = Time.zone.parse(time_string) Timecop.freeze(time_string) do |frozen_time| assert_equal expected_time, frozen_time end end def test_timezones_apply_dates Time.zone = "Central Time (US & Canada)" time = Time.zone.local(2013,1,3) Timecop.freeze(time) do assert_equal time.to_date, Time.now.to_date end end def test_set_scaling_factor_for_scale t_now = Time.now t = Time.local(2009, 10, 1, 0, 0, 30) expected_offset = t - t_now tsi = Timecop::TimeStackItem.new(:scale, 4, t) assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly" assert_equal tsi.send(:scaling_factor), 4, "Scaling factor not set" end def test_parse_only_string_with_active_support Time.expects(:parse).never Timecop.freeze(2011, 01, 02, hour=0, minute=0, second=0) end def test_parse_date Timecop.freeze(Date.new(2012, 6, 9)) end def test_time_zone_returns_nil Time.zone = nil Timecop.freeze end def test_nsecs_are_set time = Time.now Timecop.freeze time assert_equal time, Time.now assert_equal time.nsec, Time.now.nsec if (Time.now.respond_to?(:nsec)) end def test_time_with_different_timezone_keeps_nsec Time.zone = "Tokyo" t = Time.now Timecop.freeze(t) do assert_equal t, Time.now assert_equal t.nsec, Time.now.nsec if (Time.now.respond_to?(:nsec)) end end def test_time_now_always_returns_local_time Time.zone = "Tokyo" t = Time.utc(2000, 1, 1) Timecop.freeze(t) do assert_equal t.getlocal.zone, Time.now.zone end end def test_time_zone_now_returns_time_in_that_zone Time.zone = "Hawaii" t = Time.utc(2000, 1, 1) Timecop.freeze(t) do assert_equal t, Time.zone.now assert_equal 'HST', Time.zone.now.zone end end def test_freezing_a_time_leaves_timezone_intact Time.zone = "Tokyo" t = Time.now t_dup = t.dup Timecop.freeze(t) {} assert_equal t_dup.zone, t.zone end def test_freezing_a_time_with_zone_returns_proper_zones Time.zone = "Hawaii" t = ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1), ActiveSupport::TimeZone['Tokyo']) Timecop.freeze(t) do local_now = Time.now assert_equal t, local_now assert_equal t.getlocal.zone, local_now.zone zoned_now = Time.zone.now assert_equal t, zoned_now assert_equal 'HST', zoned_now.zone end end def test_datetime_timezones dt = DateTime.new(2011,1,3,15,25,0,"-6") Timecop.freeze(dt) do now = DateTime.now assert_equal dt, now, "#{dt.to_f}, #{now.to_f}" end end end timecop-0.9.1/test/timecop_without_date_but_with_time_test.rb0000644000004100000410000000031013312111520024676 0ustar www-datawww-datarequire_relative "test_helper" require "time" class TestTimecopWithoutDateButWithTime < Minitest::Test def test_loads_properly_when_time_is_required_instead_of_date require 'timecop' end end timecop-0.9.1/test/timecop_without_date_test.rb0000644000004100000410000000736013312111520021767 0ustar www-datawww-datarequire_relative "test_helper" require 'timecop' class TestTimecopWithoutDate < Minitest::Test def setup Object.send(:remove_const, :Date) if Object.const_defined?(:Date) Object.send(:remove_const, :DateTime) if Object.const_defined?(:DateTime) end # just in case...let's really make sure that Timecop is disabled between tests... def teardown Timecop.return end def test_freeze_changes_and_resets_time # depending on how we're invoked (individually or via the rake test suite) assert !Time.respond_to?(:zone) || Time.zone.nil? t = Time.local(2008, 10, 10, 10, 10, 10) assert t != Time.now Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert_equal t, Time.now end assert t != Time.now end def test_recursive_freeze t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert_equal t, Time.now t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.freeze(2008, 9, 9, 9, 9, 9) do assert_equal t2, Time.now end assert_equal t, Time.now end assert_nil Time.send(:mock_time) end def test_exception_thrown_in_freeze_block_properly_resets_time t = Time.local(2008, 10, 10, 10, 10, 10) begin Timecop.freeze(t) do assert_equal t, Time.now raise "blah exception" end rescue assert t != Time.now assert_nil Time.send(:mock_time) end end def test_freeze_freezes_time t = Time.local(2008, 10, 10, 10, 10, 10) now = Time.now Timecop.freeze(t) do sleep(0.25) assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened." new_t = Time.now assert_equal t, new_t, "Failed to change move time." # 2 seconds assert_equal new_t, Time.now end end def test_travel_keeps_time_moving t = Time.local(2008, 10, 10, 10, 10, 10) now = Time.now Timecop.travel(t) do new_now = Time.now assert_times_effectively_equal new_now, t, 1, "Looks like we failed to actually travel time" # 0.1 seconds sleep(0.25) assert_times_effectively_not_equal new_now, Time.now, 0.24, "Looks like time is not moving" end end def test_recursive_travel_maintains_each_context t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.travel(2008, 10, 10, 10, 10, 10) do assert((t - Time.now).abs < 50, "Failed to travel time.") t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.travel(2008, 9, 9, 9, 9, 9) do assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.") assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.") end assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.") end assert_nil Time.send(:mock_time) end def test_recursive_travel_then_freeze t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.travel(2008, 10, 10, 10, 10, 10) do assert((t - Time.now).abs < 50, "Failed to travel time.") t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.freeze(2008, 9, 9, 9, 9, 9) do assert_equal t2, Time.now end assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.") end assert_nil Time.send(:mock_time) end def test_recursive_freeze_then_travel t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.travel(t2) do assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.") assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.") end assert_equal t, Time.now end assert_nil Time.send(:mock_time) end end timecop-0.9.1/test/timecop_test.rb0000644000004100000410000004263713312111520017215 0ustar www-datawww-datarequire_relative "test_helper" require 'timecop' class TestTimecop < Minitest::Test def teardown Timecop.return end def test_freeze_changes_and_resets_time outer_freeze_time = Time.local(2001, 01, 01) inner_freeze_block = Time.local(2002, 02, 02) inner_freeze_one = Time.local(2003, 03, 03) inner_freeze_two = Time.local(2004, 04, 04) Timecop.freeze(outer_freeze_time) do assert_times_effectively_equal outer_freeze_time, Time.now Timecop.freeze(inner_freeze_block) do assert_times_effectively_equal inner_freeze_block, Time.now Timecop.freeze(inner_freeze_one) assert_times_effectively_equal inner_freeze_one, Time.now Timecop.freeze(inner_freeze_two) assert_times_effectively_equal inner_freeze_two, Time.now end assert_times_effectively_equal outer_freeze_time, Time.now end end def test_freeze_yields_mocked_time Timecop.freeze(2008, 10, 10, 10, 10, 10) do |frozen_time| assert_equal frozen_time, Time.now end end def test_freeze_then_return_unsets_mock_time Timecop.freeze(1) Timecop.return assert_nil Time.send(:mock_time) end def test_travel_then_return_unsets_mock_time Timecop.travel(1) Timecop.return assert_nil Time.send(:mock_time) end def test_freeze_with_block_unsets_mock_time assert_nil Time.send(:mock_time), "test is invalid" Timecop.freeze(1) do; end assert_nil Time.send(:mock_time) end def test_travel_with_block_unsets_mock_time assert_nil Time.send(:mock_time), "test is invalid" Timecop.travel(1) do; end assert_nil Time.send(:mock_time) end def test_travel_does_not_reduce_precision_of_datetime # requires to_r on Float (>= 1.9) if Float.method_defined?(:to_r) Timecop.travel(Time.new(2014, 1, 1, 0, 0, 0)) assert DateTime.now != DateTime.now Timecop.travel(Time.new(2014, 1, 1, 0, 0, 59)) assert DateTime.now != DateTime.now end end def test_freeze_in_time_subclass_returns_mocked_subclass t = Time.local(2008, 10, 10, 10, 10, 10) custom_timeklass = Class.new(Time) do def custom_format_method() strftime('%F') end end Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert custom_timeklass.now.is_a? custom_timeklass assert Time.now.eql? custom_timeklass.now assert custom_timeklass.now.respond_to? :custom_format_method end end def test_freeze_in_date_subclass_returns_mocked_subclass t = Time.local(2008, 10, 10, 10, 10, 10) custom_dateklass = Class.new(Date) do def custom_format_method() strftime('%F') end end Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert custom_dateklass.today.is_a? custom_dateklass assert Date.today.eql? custom_dateklass.today assert custom_dateklass.today.respond_to? :custom_format_method end end def test_freeze_in_datetime_subclass_returns_mocked_subclass t = Time.local(2008, 10, 10, 10, 10, 10) custom_datetimeklass = Class.new(DateTime) do def custom_format_method() strftime('%F') end end Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert custom_datetimeklass.now.is_a? custom_datetimeklass assert DateTime.now.eql? custom_datetimeklass.now assert custom_datetimeklass.now.respond_to? :custom_format_method end end def test_recursive_freeze t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert_equal t, Time.now t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.freeze(2008, 9, 9, 9, 9, 9) do assert_equal t2, Time.now end assert_equal t, Time.now end assert t != Time.now end def test_freeze_with_time_instance_works_as_expected t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now assert_date_times_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now assert_equal Date.new(2008, 10, 10), Date.today end assert t != Time.now assert DateTime.new(2008, 10, 10, 10, 10, 10, local_offset) != DateTime.now assert Date.new(2008, 10, 10) != Date.today end def test_freeze_with_datetime_on_specific_timezone_during_dst each_timezone do # Start from a time that is subject to DST Timecop.freeze(2009, 9, 1) # Travel to a DateTime that is also in DST t = DateTime.parse("2009-10-11 00:38:00 +0200") Timecop.freeze(t) do assert_date_times_equal t, DateTime.now end Timecop.return end end def test_freeze_with_datetime_on_specific_timezone_not_during_dst each_timezone do # Start from a time that is not subject to DST Timecop.freeze(2009, 12, 1) # Travel to a time that is also not in DST t = DateTime.parse("2009-12-11 00:38:00 +0100") Timecop.freeze(t) do assert_date_times_equal t, DateTime.now end end end def test_freeze_with_datetime_from_a_non_dst_time_to_a_dst_time each_timezone do # Start from a time that is not subject to DST Timecop.freeze(DateTime.parse("2009-12-1 00:00:00 +0100")) # Travel back to a time in DST t = DateTime.parse("2009-10-11 00:38:00 +0200") Timecop.freeze(t) do assert_date_times_equal t, DateTime.now end end end def test_freeze_with_datetime_from_a_dst_time_to_a_non_dst_time each_timezone do # Start from a time that is not subject to DST Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 +0200")) # Travel back to a time in DST t = DateTime.parse("2009-12-1 00:38:00 +0100") Timecop.freeze(t) do assert_date_times_equal t, DateTime.now end end end def test_freeze_with_date_instance_works_as_expected d = Date.new(2008, 10, 10) Timecop.freeze(d) do assert_equal d, Date.today assert_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now assert_date_times_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now end assert d != Date.today assert Time.local(2008, 10, 10, 0, 0, 0) != Time.now assert DateTime.new(2008, 10, 10, 0, 0, 0, local_offset) != DateTime.now end def test_freeze_with_integer_instance_works_as_expected t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now assert_date_times_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now assert_equal Date.new(2008, 10, 10), Date.today Timecop.freeze(10) do assert_equal t + 10, Time.now assert_equal Time.local(2008, 10, 10, 10, 10, 20), Time.now assert_equal Date.new(2008, 10, 10), Date.today end end assert t != Time.now assert DateTime.new(2008, 10, 10, 10, 10, 10) != DateTime.now assert Date.new(2008, 10, 10) != Date.today end def test_exception_thrown_in_freeze_block_properly_resets_time t = Time.local(2008, 10, 10, 10, 10, 10) begin Timecop.freeze(t) do assert_equal t, Time.now raise "blah exception" end rescue assert t != Time.now assert_nil Time.send(:mock_time) end end def test_exception_thrown_in_return_block_restores_previous_time t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do Timecop.return { raise 'foobar' } rescue nil assert_equal t, Time.now end end def test_freeze_freezes_time t = Time.local(2008, 10, 10, 10, 10, 10) now = Time.now Timecop.freeze(t) do #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened." new_t, new_d, new_dt = Time.now, Date.today, DateTime.now assert_equal t, new_t, "Failed to freeze time." # 2 seconds #sleep(10) assert_equal new_t, Time.now assert_equal new_d, Date.today assert_equal new_dt, DateTime.now end end def test_travel_keeps_time_moving t = Time.local(2008, 10, 10, 10, 10, 10) now = Time.now Timecop.travel(t) do new_now = Time.now assert_times_effectively_equal(new_now, t, 1, "Looks like we failed to actually travel time") sleep(0.25) assert_times_effectively_not_equal new_now, Time.now, 0.24, "Looks like time is not moving" end end def test_mocked_date_time_now_is_local each_timezone do t = DateTime.parse("2009-10-11 00:38:00 +0200") Timecop.freeze(t) do if ENV['TZ'] == 'UTC' assert_equal(local_offset, 0, "Local offset not be zero for #{ENV['TZ']}") else assert(local_offset, 0 != "Local offset should not be zero for #{ENV['TZ']}") end assert_equal local_offset, DateTime.now.offset, "Failed for timezone: #{ENV['TZ']}" end end end def test_scaling_keeps_time_moving_at_an_accelerated_rate t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.scale(4, t) do start = Time.now assert_times_effectively_equal start, t, 1, "Looks like we failed to actually travel time" sleep(0.25) assert_times_effectively_equal Time.at((start + 4*0.25).to_f), Time.now, 0.25, "Looks like time is not moving at 4x" end end def test_scaling_returns_now_if_no_block_given t = Time.local(2008, 10, 10, 10, 10, 10) assert_times_effectively_equal t, Timecop.scale(4, t) end def test_freeze_with_utc_time each_timezone do t = Time.utc(2008, 10, 10, 10, 10, 10) local = t.getlocal Timecop.freeze(t) do assert_equal local, Time.now, "Failed for timezone: #{ENV['TZ']}" end end end def test_freeze_without_arguments_instance_works_as_expected t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now Timecop.freeze do assert_equal t, Time.now assert_equal Time.local(2008, 10, 10, 10, 10, 10), Time.now assert_equal Date.new(2008, 10, 10), Date.today end end assert t != Time.now end def test_destructive_methods_on_frozen_time # Use any time zone other than UTC. ENV['TZ'] = 'EST' t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert !Time.now.utc?, "Time#local failed to return a time in the local time zone." # #utc, #gmt, and #localtime are destructive methods. Time.now.utc assert !Time.now.utc?, "Failed to thwart destructive methods." end end def test_recursive_travel_maintains_each_context t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.travel(2008, 10, 10, 10, 10, 10) do assert((t - Time.now).abs < 50, "Failed to travel time.") t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.travel(2008, 9, 9, 9, 9, 9) do assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.") assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.") end assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.") end assert_nil Time.send(:mock_time) end def test_recursive_travel_yields_correct_time Timecop.travel(2008, 10, 10, 10, 10, 10) do Timecop.travel(2008, 9, 9, 9, 9, 9) do |inner_freeze| assert_times_effectively_equal inner_freeze, Time.now, 1, "Failed to yield current time back to block" end end end def test_recursive_travel_then_freeze t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.travel(2008, 10, 10, 10, 10, 10) do assert((t - Time.now).abs < 50, "Failed to travel time.") t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.freeze(2008, 9, 9, 9, 9, 9) do assert_equal t2, Time.now end assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.") end assert_nil Time.send(:mock_time) end def test_recursive_freeze_then_travel t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.travel(t2) do assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.") assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.") end assert_equal t, Time.now end assert_nil Time.send(:mock_time) end def test_travel_time_returns_now_if_no_block_given t_future = Time.local(2030, 10, 10, 10, 10, 10) assert_times_effectively_equal t_future, Timecop.travel(t_future) end def test_return_temporarily_returns_to_current_time_in_given_block time_after_travel = Time.local(1990, 7, 16) now = Time.now Timecop.travel(time_after_travel) assert_times_effectively_equal(time_after_travel, Time.now) Timecop.return do assert_times_effectively_equal(now, Time.now) end assert_times_effectively_equal(time_after_travel, Time.now) end def test_travel_time_with_block_returns_the_value_of_the_block t_future = Time.local(2030, 10, 10, 10, 10, 10) expected = :foo actual = Timecop.travel(t_future) { expected } assert_equal expected, actual end def test_freeze_time_returns_now_if_no_block_given t_future = Time.local(2030, 10, 10, 10, 10, 10) assert_times_effectively_equal t_future, Timecop.freeze(t_future) end def test_freeze_time_with_block_returns_the_value_of_the_block t_future = Time.local(2030, 10, 10, 10, 10, 10) expected = :foo actual = Timecop.freeze(t_future) { expected } assert_equal expected, actual end def test_return_returns_nil assert_nil Timecop.return end def test_freeze_without_params Timecop.freeze 1 do current_time = Time.now Timecop.freeze do assert_equal Time.now, current_time end end end def test_freeze_with_new_date date = Date.new(2012, 6, 9) Timecop.freeze(Date.new(2012, 6, 9)) do assert_equal date, Time.now.__send__(:to_date) end end def test_return_to_baseline_without_a_baseline_set_returns_to_current_time time_before_travel = Time.now Timecop.travel Time.now - 60 Timecop.return_to_baseline assert times_effectively_equal(time_before_travel, Time.now) end def test_return_to_baseline_with_a_baseline_set_returns_to_baseline baseline = Time.local(1945, 10, 10, 10, 10, 10) Timecop.baseline = baseline Timecop.travel Time.now - 60 time_now = Timecop.return_to_baseline assert times_effectively_equal(baseline, time_now), "expected to return to #{baseline}, but returned to #{time_now}" end def test_return_eliminates_baseline time_before_travel = Time.now Timecop.baseline = Time.local(1937, 9, 9, 9, 9, 9) Timecop.return assert times_effectively_equal(time_before_travel, Time.now) Timecop.travel(Time.now - 100) Timecop.return_to_baseline assert times_effectively_equal(time_before_travel, Time.now) end def test_mock_time_new_same_as_now date = Time.local(2011, 01, 02) Timecop.freeze date assert_equal date, Time.now assert_equal date, Time.new end def test_not_callable_send_travel assert_raises NoMethodError do Timecop.send_travel(:travel, Time.now - 100) end end def test_datetime_to_time_for_dst_to_non_dst # Start at a time subject to DST Timecop.travel(2009, 4, 1, 0, 0, 0, -4*60*60) do # Then freeze, via DateTime, at a time not subject to DST t = DateTime.new(2009,01,01,0,0,0, "-0500") Timecop.freeze(t) do # Check the current time via DateTime.now--should be what we asked for assert_date_times_equal t, DateTime.now # Then check the current time via Time.now (not DateTime.now) assert_times_effectively_equal Time.new(2009, 1, 1, 0, 0, 0, -5*60*60), Time.now end end end def test_raises_when_safe_mode_and_no_block with_safe_mode do assert_raises Timecop::SafeModeException do Timecop.freeze end end end def test_raises_when_safe_mode_and_no_block_though_previously_block_given Timecop.freeze do Timecop.freeze end with_safe_mode do assert_raises Timecop::SafeModeException do Timecop.freeze end end end def test_no_raise_when_safe_mode_and_block_used with_safe_mode do Timecop.freeze {} end end def test_no_raise_when_not_safe_mode_and_no_block with_safe_mode(false) do Timecop.freeze end end def test_no_raise_when_safe_mode_and_no_block_and_in_block_context with_safe_mode do Timecop.freeze do Timecop.freeze end end end def test_date_strptime_without_year Timecop.freeze(Time.new(1984,2,28)) do assert_equal Date.strptime('04-14', '%m-%d'), Date.new(1984, 4, 14) end end def test_date_strptime_without_specifying_format Timecop.freeze(Time.new(1984,2,28)) do assert_equal Date.strptime('1999-04-14'), Date.new(1999, 4, 14) end end def test_frozen_after_freeze Timecop.freeze assert Timecop.frozen? end def test_frozen_inside_freeze Timecop.freeze do assert Timecop.frozen? end end def test_not_frozen_after_return Timecop.freeze Timecop.return assert !Timecop.frozen? end def test_thread_safe_timecop Timecop.thread_safe = true date = Time.local(2011, 01, 02) thread = Thread.new do Timecop.freeze(date) do sleep 1 #give main thread time to run assert_equal date, Time.now end end sleep 0.25 assert Time.now != date thread.join ensure Timecop.thread_safe = false end private def with_safe_mode(enabled=true) mode = Timecop.safe_mode? Timecop.safe_mode = enabled yield ensure Timecop.safe_mode = mode end end timecop-0.9.1/test/test_helper.rb0000644000004100000410000000323013312111520017016 0ustar www-datawww-datarequire 'bundler/setup' require 'minitest/autorun' require 'minitest/rg' $VERBOSE = true # enable ruby warnings require 'mocha/setup' class Minitest::Test private # Tests to see that two times are within the given distance, # in seconds, from each other. def times_effectively_equal(time1, time2, seconds_interval = 1) (time1 - time2).abs <= seconds_interval end def assert_times_effectively_equal(time1, time2, seconds_interval = 1, msg = nil) assert times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}" end def assert_times_effectively_not_equal(time1, time2, seconds_interval = 1, msg = nil) assert !times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}" end # Gets the local offset (supplied by ENV['TZ'] or your computer's clock) # At the given timestamp, or Time.now if not time is given. def local_offset(time = Time.now) Time.at(time.to_i).to_datetime.offset end TIMEZONES = ["Europe/Paris", "UTC", "America/Chicago"] def each_timezone old_tz = ENV["TZ"] begin TIMEZONES.each do |timezone| ENV["TZ"] = timezone yield end ensure ENV["TZ"] = old_tz end end def a_time_stack_item Timecop::TimeStackItem.new(:freeze, 2008, 1, 1, 0, 0, 0) end def assert_date_times_equal(dt1, dt2) assert_in_delta dt1.to_time.to_f, dt2.to_time.to_f, 0.01, "Failed for timezone: #{ENV['TZ']}: #{dt1.to_s} not equal to #{dt2.to_s}" end def jruby? RUBY_PLATFORM == "java" end end timecop-0.9.1/LICENSE0000644000004100000410000000211013312111520014175 0ustar www-datawww-data(The MIT License) Copyright (c) 2012 — Travis Jeffery, John Trupiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. timecop-0.9.1/timecop.gemspec0000644000004100000410000000407113312111520016205 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: timecop 0.9.1 ruby lib Gem::Specification.new do |s| s.name = "timecop".freeze s.version = "0.9.1" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Travis Jeffery".freeze, "John Trupiano".freeze] s.date = "2017-07-05" s.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.".freeze s.email = "travisjeffery@gmail.com".freeze s.extra_rdoc_files = ["LICENSE".freeze, "README.markdown".freeze] s.files = ["LICENSE".freeze, "README.markdown".freeze, "Rakefile".freeze, "lib/timecop.rb".freeze, "lib/timecop/time_extensions.rb".freeze, "lib/timecop/time_stack_item.rb".freeze, "lib/timecop/timecop.rb".freeze, "lib/timecop/version.rb".freeze, "test/test_helper.rb".freeze, "test/time_stack_item_test.rb".freeze, "test/timecop_test.rb".freeze, "test/timecop_without_date_but_with_time_test.rb".freeze, "test/timecop_without_date_test.rb".freeze] s.homepage = "https://github.com/travisjeffery/timecop".freeze s.licenses = ["MIT".freeze] s.rdoc_options = ["--charset=UTF-8".freeze] s.required_ruby_version = Gem::Requirement.new(">= 1.9.2".freeze) s.rubyforge_project = "timecop".freeze s.rubygems_version = "2.5.2.1".freeze s.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.".freeze s.test_files = ["test/test_helper.rb".freeze, "test/time_stack_item_test.rb".freeze, "test/timecop_test.rb".freeze, "test/timecop_without_date_but_with_time_test.rb".freeze, "test/timecop_without_date_test.rb".freeze] end timecop-0.9.1/Rakefile0000644000004100000410000000140113312111520014637 0ustar www-datawww-datarequire 'bundler/setup' require 'bundler/gem_tasks' require 'rake/testtask' require 'rdoc/task' Rake::RDocTask.new do |rdoc| if File.exist?('VERSION') version = File.read('VERSION') else version = "" end rdoc.rdoc_dir = 'rdoc' rdoc.options << '--line-numbers' << '--inline-source' rdoc.title = "timecop #{version}" rdoc.rdoc_files.include('README*') rdoc.rdoc_files.include('History.rdoc') rdoc.rdoc_files.include('lib/**/*.rb') end task :test do failed = Dir["test/*_test.rb"].map do |test| command = "ruby #{test}" puts puts command command unless system(command) end.compact if failed.any? abort "#{failed.count} Tests failed\n#{failed.join("\n")}" end end desc 'Default: run tests' task :default => [:test] timecop-0.9.1/lib/0000755000004100000410000000000013312111520013744 5ustar www-datawww-datatimecop-0.9.1/lib/timecop.rb0000644000004100000410000000020013312111520015721 0ustar www-datawww-datarequire File.join(File.dirname(__FILE__), "timecop", "timecop") require File.join(File.dirname(__FILE__), "timecop", "version") timecop-0.9.1/lib/timecop/0000755000004100000410000000000013312111520015404 5ustar www-datawww-datatimecop-0.9.1/lib/timecop/version.rb0000644000004100000410000000004613312111520017416 0ustar www-datawww-dataclass Timecop VERSION = "0.9.1" end timecop-0.9.1/lib/timecop/time_extensions.rb0000644000004100000410000000635313312111520021155 0ustar www-datawww-datarequire 'time' require 'date' class Time #:nodoc: class << self def mock_time mocked_time_stack_item = Timecop.top_stack_item mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time(self) end alias_method :now_without_mock_time, :now def now_with_mock_time mock_time || now_without_mock_time end alias_method :now, :now_with_mock_time alias_method :new_without_mock_time, :new def new_with_mock_time(*args) args.size <= 0 ? now : new_without_mock_time(*args) end alias_method :new, :new_with_mock_time end end class Date #:nodoc: class << self def mock_date mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date(self) end alias_method :today_without_mock_date, :today def today_with_mock_date mock_date || today_without_mock_date end alias_method :today, :today_with_mock_date alias_method :strptime_without_mock_date, :strptime def strptime_with_mock_date(str = '-4712-01-01', fmt = '%F', start = Date::ITALY) unless start == Date::ITALY raise ArgumentError, "Timecop's #{self}::#{__method__} only " + "supports Date::ITALY for the start argument." end Time.strptime(str, fmt).to_date end alias_method :strptime, :strptime_with_mock_date def parse_with_mock_date(*args) parsed_date = parse_without_mock_date(*args) return parsed_date unless mocked_time_stack_item date_hash = Date._parse(*args) case when date_hash[:year] && date_hash[:mon] parsed_date when date_hash[:mon] && date_hash[:mday] Date.new(mocked_time_stack_item.year, date_hash[:mon], date_hash[:mday]) when date_hash[:wday] closest_wday(date_hash[:wday]) else parsed_date + mocked_time_stack_item.travel_offset_days end end alias_method :parse_without_mock_date, :parse alias_method :parse, :parse_with_mock_date def mocked_time_stack_item Timecop.top_stack_item end def closest_wday(wday) today = Date.today result = today - today.wday result += 1 until wday == result.wday result end end end class DateTime #:nodoc: class << self def mock_time mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime(self) end def now_with_mock_time mock_time || now_without_mock_time end alias_method :now_without_mock_time, :now alias_method :now, :now_with_mock_time def parse_with_mock_date(*args) date_hash = Date._parse(*args) parsed_date = parse_without_mock_date(*args) return parsed_date unless mocked_time_stack_item date_hash = DateTime._parse(*args) case when date_hash[:year] && date_hash[:mon] parsed_date when date_hash[:mon] && date_hash[:mday] DateTime.new(mocked_time_stack_item.year, date_hash[:mon], date_hash[:mday]) when date_hash[:wday] Date.closest_wday(date_hash[:wday]).to_datetime else parsed_date + mocked_time_stack_item.travel_offset_days end end alias_method :parse_without_mock_date, :parse alias_method :parse, :parse_with_mock_date def mocked_time_stack_item Timecop.top_stack_item end end end timecop-0.9.1/lib/timecop/timecop.rb0000644000004100000410000001450013312111520017371 0ustar www-datawww-datarequire 'singleton' require File.join(File.dirname(__FILE__), "time_extensions") require File.join(File.dirname(__FILE__), "time_stack_item") # Timecop # * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects # * Allows us to "freeze" time in our Ruby applications. # * Optionally allows time travel to simulate a running clock, such time is not technically frozen. # # This is very useful when your app's functionality is dependent on time (e.g. # anything that might expire). This will allow us to alter the return value of # Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change. class Timecop include Singleton class << self # Allows you to run a block of code and "fake" a time throughout the execution of that block. # This is particularly useful for writing test methods where the passage of time is critical to the business # logic being tested. For example: # # joe = User.find(1) # joe.purchase_home() # assert !joe.mortgage_due? # Timecop.freeze(2008, 10, 5) do # assert joe.mortgage_due? # end # # freeze and travel will respond to several different arguments: # 1. Timecop.freeze(time_inst) # 2. Timecop.freeze(datetime_inst) # 3. Timecop.freeze(date_inst) # 4. Timecop.freeze(offset_in_seconds) # 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0) # 6. Timecop.freeze() # Defaults to Time.now # # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their # previous values after the block has finished executing. This allows us to nest multiple # calls to Timecop.travel and have each block maintain it's concept of "now." # # * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if # benchmark or other timing calls are executed, which implicitly expect Time to actually move # forward. # # * Rails Users: Be especially careful when setting this in your development environment in a # rails project. Generators will load your environment, including the migration generator, # which will lead to files being generated with the timestamp set by the Timecop.freeze call # in your dev environment # # Returns the value of the block if one is given, or the mocked time. def freeze(*args, &block) send_travel(:freeze, *args, &block) end # Allows you to run a block of code and "fake" a time throughout the execution of that block. # See Timecop#freeze for a sample of how to use (same exact usage syntax) # # * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly # good candidate for use in environment files in rails projects. # # Returns the value of the block if one is given, or the mocked time. def travel(*args, &block) send_travel(:travel, *args, &block) end # Allows you to run a block of code and "scale" a time throughout the execution of that block. # The first argument is a scaling factor, for example: # Timecop.scale(2) do # ... time will 'go' twice as fast here # end # See Timecop#freeze for exact usage of the other arguments # # Returns the value of the block if one is given, or the mocked time. def scale(*args, &block) send_travel(:scale, *args, &block) end def baseline instance.send(:baseline) end def baseline=(baseline) instance.send(:baseline=, baseline) end # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists) permamently when # no block argument is given, or temporarily reverts back to the system's time temporarily for # the given block. def return(&block) if block_given? instance.send(:return, &block) else instance.send(:unmock!) nil end end def return_to_baseline instance.send(:return_to_baseline) Time.now end def top_stack_item #:nodoc: instance.send(:stack).last end def safe_mode=(safe) @safe_mode = safe end def safe_mode? @safe_mode ||= false end def thread_safe=(t) instance.send(:thread_safe=, t) end def thread_safe instance.send(:thread_safe) end # Returns whether or not Timecop is currently frozen/travelled def frozen? !instance.send(:stack).empty? end private def send_travel(mock_type, *args, &block) val = instance.send(:travel, mock_type, *args, &block) block_given? ? val : Time.now end end private def baseline=(b) set_baseline(b) stack << TimeStackItem.new(:travel, b) end def baseline if @thread_safe Thread.current[:timecop_baseline] else @baseline end end def set_baseline(b) if @thread_safe Thread.current[:timecop_baseline] = b else @baseline = b end end def stack if @thread_safe Thread.current[:timecop_stack] ||= [] Thread.current[:timecop_stack] else @stack end end def set_stack(s) if @thread_safe Thread.current[:timecop_stack] = s else @stack = s end end def initialize #:nodoc: @stack = [] @safe = nil @thread_safe = false end def thread_safe=(t) initialize @thread_safe = t end def thread_safe @thread_safe end def travel(mock_type, *args, &block) #:nodoc: raise SafeModeException if Timecop.safe_mode? && !block_given? && !@safe stack_item = TimeStackItem.new(mock_type, *args) stack_backup = stack.dup stack << stack_item if block_given? safe_backup = @safe @safe = true begin yield stack_item.time ensure @stack.replace stack_backup @safe = safe_backup end end end def return(&block) current_stack = stack current_baseline = baseline unmock! yield ensure set_stack current_stack set_baseline current_baseline end def unmock! #:nodoc: set_baseline nil set_stack [] end def return_to_baseline if baseline set_stack [stack.shift] else unmock! end end class SafeModeException < StandardError def initialize super "Safe mode is enabled, only calls passing a block are allowed." end end end timecop-0.9.1/lib/timecop/time_stack_item.rb0000644000004100000410000000732313312111520021077 0ustar www-datawww-dataclass Timecop # A data class for carrying around "time movement" objects. Makes it easy to keep track of the time # movements on a simple stack. class TimeStackItem #:nodoc: attr_reader :mock_type def initialize(mock_type, *args) raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel, :scale].include?(mock_type) @travel_offset = @scaling_factor = nil @scaling_factor = args.shift if mock_type == :scale @mock_type = mock_type @time = parse_time(*args) @time_was = Time.now_without_mock_time @travel_offset = compute_travel_offset end def year time.year end def month time.month end def day time.day end def hour time.hour end def min time.min end def sec time.sec end def utc_offset time.utc_offset end def travel_offset @travel_offset unless mock_type == :freeze end def travel_offset_days (@travel_offset / 60 / 60 / 24).round end def scaling_factor @scaling_factor end def time(time_klass = Time) #:nodoc: if @time.respond_to?(:in_time_zone) time = time_klass.at(@time.dup.localtime) else time = time_klass.at(@time) end if travel_offset.nil? time elsif scaling_factor.nil? time_klass.at(Time.now_without_mock_time + travel_offset) else time_klass.at(scaled_time) end end def scaled_time (@time + (Time.now_without_mock_time - @time_was) * scaling_factor).to_f end def date(date_klass = Date) date_klass.jd(time.__send__(:to_date).jd) end def datetime(datetime_klass = DateTime) if Float.method_defined?(:to_r) fractions_of_a_second = time.to_f % 1 datetime_klass.new(year, month, day, hour, min, (fractions_of_a_second + sec), utc_offset_to_rational(utc_offset)) else datetime_klass.new(year, month, day, hour, min, sec, utc_offset_to_rational(utc_offset)) end end private def rational_to_utc_offset(rational) ((24.0 / rational.denominator) * rational.numerator) * (60 * 60) end def utc_offset_to_rational(utc_offset) Rational(utc_offset, 24 * 60 * 60) end def parse_time(*args) arg = args.shift if arg.is_a?(Time) arg elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime) time_klass.at(arg.to_time.to_f).getlocal elsif Object.const_defined?(:Date) && arg.is_a?(Date) time_klass.local(arg.year, arg.month, arg.day, 0, 0, 0) elsif args.empty? && (arg.kind_of?(Integer) || arg.kind_of?(Float)) time_klass.now + arg elsif arg.nil? time_klass.now else if arg.is_a?(String) && Time.respond_to?(:parse) time_klass.parse(arg) else # we'll just assume it's a list of y/m/d/h/m/s year = arg || 2000 month = args.shift || 1 day = args.shift || 1 hour = args.shift || 0 minute = args.shift || 0 second = args.shift || 0 time_klass.local(year, month, day, hour, minute, second) end end end def compute_travel_offset time - Time.now_without_mock_time end def times_are_equal_within_epsilon t1, t2, epsilon_in_seconds (t1 - t2).abs < epsilon_in_seconds end def time_klass Time.respond_to?(:zone) && Time.zone ? Time.zone : Time end end end timecop-0.9.1/README.markdown0000644000004100000410000001165713312111520015711 0ustar www-datawww-data# timecop [![Build Status](https://secure.travis-ci.org/travisjeffery/timecop.svg)](http://travis-ci.org/travisjeffery/timecop) ## 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. ## INSTALL `gem install timecop` ## FEATURES - Freeze time to a specific point. - Travel back to a specific point in time, but allow time to continue moving forward from there. - Scale time by a given scaling factor that will cause time to move at an accelerated pace. - No dependencies, can be used with _any_ ruby project - Timecop api allows arguments to be passed into #freeze and #travel as one of the following: - Time instance - DateTime instance - Date instance - individual arguments (year, month, day, hour, minute, second) - a single integer argument that is interpreted as an offset in seconds from Time.now - Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now. - Works with regular Ruby projects, and Ruby on Rails projects ## USAGE Run a time-sensitive test ```ruby joe = User.find(1) joe.purchase_home() assert !joe.mortgage_due? # move ahead a month and assert that the mortgage is due Timecop.freeze(Date.today + 30) do assert joe.mortgage_due? end ``` You can mock the time for a set of tests easily via setup/teardown methods ```ruby describe "some set of tests to mock" do before do Timecop.freeze(Time.local(1990)) end after do Timecop.return end it "should do blah blah blah" do end end ``` 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) in config/environments/test.rb ```ruby config.after_initialize do # Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward t = Time.local(2008, 9, 1, 10, 5, 0) Timecop.travel(t) end ``` ### The difference between Timecop.freeze and Timecop.travel 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: ```ruby new_time = Time.local(2008, 9, 1, 12, 0, 0) Timecop.freeze(new_time) sleep(10) new_time == Time.now # ==> true Timecop.return # "turn off" Timecop Timecop.travel(new_time) sleep(10) new_time == Time.now # ==> false ``` ### Timecop.scale Let's say you want to test a "live" integration wherein entire days could pass by in minutes while you're able to simulate "real" activity. For example, one such use case is being able to test reports and invoices that run in 30 day cycles in very little time, while also being able to simulate activity via subsequent calls to your application. ```ruby # seconds will now seem like hours Timecop.scale(3600) Time.now # => 2012-09-20 21:23:25 -0500 # seconds later, hours have passed and it's gone from 9pm at night to 6am in the morning Time.now # => 2012-09-21 06:22:59 -0500 ``` See [#42](https://github.com/travisjeffery/timecop/pull/42) for more information, thanks to Ken Mayer, David Holcomb, and Pivotal Labs. ### Timecop.safe_mode Safe mode forces you to use Timecop with the block syntax since it always puts time back the way it was. If you are running in safe mode and use Timecop without the block syntax `Timecop::SafeModeException` will be raised to tell the user they are not being safe. ``` ruby # turn on safe mode Timecop.safe_mode = true # check if you are in safe mode Timecop.safe_mode? # => true # using method without block Timecop.freeze # => Timecop::SafeModeException: Safe mode is enabled, only calls passing a block are allowed. ``` ### Rails v Ruby Date/Time libraries Sometimes [Rails Date/Time methods don't play nicely with Ruby Date/Time methods.](https://rails.lighthouseapp.com/projects/8994/tickets/6410-dateyesterday-datetoday) Be careful mixing Ruby `Date.today` with Rails `Date.tomorrow` / `Date.yesterday` as things might break. ## Contribute timecop is maintained by [travisjeffery](http://github.com/travisjeffery), and was created by [jtrupiano](https://github.com/jtrupiano). Here's the most direct way to get your work merged into the project. - Fork the project - Clone down your fork - Create a feature branch - Hack away and add tests, not necessarily in that order - Make sure everything still passes by running tests - If necessary, rebase your commits into logical chunks without errors - Push the branch up to your fork - Send a pull request for your branch