aa84a783ee
Ref: https://bugs.ruby-lang.org/issues/15554 This new Ruby 3.4 warning is still being fined tuned to reduce false positives, so we shouldn't fail builds on it just yet. It however caught one mistake in the test suite which is valuable.
415 lines
13 KiB
Ruby
415 lines
13 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative "abstract_unit"
|
|
require "active_support/core_ext/date_time"
|
|
require "active_support/core_ext/numeric/time"
|
|
require "active_support/core_ext/string/conversions"
|
|
require_relative "time_zone_test_helpers"
|
|
|
|
class TimeTravelTest < ActiveSupport::TestCase
|
|
include TimeZoneTestHelpers
|
|
|
|
class TimeSubclass < ::Time; end
|
|
class DateSubclass < ::Date; end
|
|
class DateTimeSubclass < ::DateTime; end
|
|
|
|
class TravelClass
|
|
include ActiveSupport::Testing::TimeHelpers
|
|
|
|
def travel_to_no_block(date)
|
|
travel_to(date)
|
|
end
|
|
|
|
def travel_to_block(date)
|
|
travel_to(date) { }
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel
|
|
Time.stub(:now, Time.now) do
|
|
expected_time = Time.now + 1.day
|
|
travel 1.day
|
|
|
|
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
|
|
assert_equal expected_time.to_date, Date.today
|
|
assert_equal expected_time.to_datetime.to_fs(:db), DateTime.now.to_fs(:db)
|
|
|
|
assert_equal expected_time.to_fs(:db), Time.new.to_fs(:db)
|
|
if RUBY_VERSION >= "3.2"
|
|
assert_not_equal expected_time.to_fs(:db), Time.new(precision: 3).to_fs(:db)
|
|
end
|
|
ensure
|
|
travel_back
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_with_block
|
|
Time.stub(:now, Time.now) do
|
|
expected_time = Time.now + 1.day
|
|
|
|
travel 1.day do
|
|
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
|
|
assert_equal expected_time.to_date, Date.today
|
|
assert_equal expected_time.to_datetime.to_fs(:db), DateTime.now.to_fs(:db)
|
|
|
|
assert_equal expected_time.to_fs(:db), Time.new.to_fs(:db)
|
|
if RUBY_VERSION >= "3.2"
|
|
assert_not_equal expected_time.to_fs(:db), Time.new(precision: 3).to_fs(:db)
|
|
assert_equal Time.new("2000-12-31 23:59:59.567"), Time.new("2000-12-31 23:59:59.56789", precision: 3)
|
|
end
|
|
end
|
|
|
|
assert_not_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
|
|
assert_not_equal expected_time.to_date, Date.today
|
|
assert_not_equal expected_time.to_datetime.to_fs(:db), DateTime.now.to_fs(:db)
|
|
if RUBY_VERSION >= "3.2"
|
|
assert_equal Time.new("2000-12-31 23:59:59.567"), Time.new("2000-12-31 23:59:59.56789", precision: 3)
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to
|
|
Time.stub(:now, Time.now) do
|
|
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
travel_to expected_time
|
|
|
|
assert_equal expected_time, Time.now
|
|
assert_equal expected_time, Time.new
|
|
assert_not_equal expected_time, Time.new(2004, 11, 25)
|
|
if RUBY_VERSION >= "3.2"
|
|
assert_not_equal expected_time, Time.new(precision: 3)
|
|
end
|
|
assert_equal Date.new(2004, 11, 24), Date.today
|
|
assert_equal expected_time.to_datetime, DateTime.now
|
|
ensure
|
|
travel_back
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_block
|
|
Time.stub(:now, Time.now) do
|
|
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
|
|
travel_to expected_time do
|
|
assert_equal expected_time, Time.now
|
|
assert_equal expected_time, Time.new
|
|
if RUBY_VERSION >= "3.2"
|
|
assert_not_equal expected_time, Time.new(precision: 3)
|
|
end
|
|
assert_not_equal expected_time, Time.new(2004, 11, 25)
|
|
assert_equal Date.new(2004, 11, 24), Date.today
|
|
assert_equal expected_time.to_datetime, DateTime.now
|
|
end
|
|
|
|
assert_not_equal expected_time, Time.now
|
|
assert_not_equal expected_time, Time.new
|
|
assert_not_equal Date.new(2004, 11, 24), Date.today
|
|
assert_not_equal expected_time.to_datetime, DateTime.now
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_time_zone
|
|
with_env_tz "US/Eastern" do
|
|
with_tz_default ActiveSupport::TimeZone["UTC"] do
|
|
Time.stub(:now, Time.now) do
|
|
expected_time = 5.minutes.ago
|
|
|
|
travel_to 5.minutes.ago do
|
|
assert_equal expected_time.to_fs(:db), Time.zone.now.to_fs(:db)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_different_system_and_application_time_zones
|
|
with_env_tz "US/Eastern" do # system time zone: -05
|
|
expected_time_in_2021 = Time.new(2021)
|
|
|
|
with_tz_default ActiveSupport::TimeZone["Ekaterinburg"] do # application time zone: +05
|
|
destination_time = Time.new(2023, 12, 1, 5, 6, 7, 5 * 3600)
|
|
|
|
# All stubbed methods are expected to return values in system (-05) time zone
|
|
expected_utc_offset = -5 * 3600
|
|
expected_time = Time.new(2023, 11, 30, 19, 6, 7, expected_utc_offset)
|
|
expected_datetime = DateTime.new(2023, 11, 30, 19, 6, 7, -Rational(5, 24))
|
|
expected_date = Date.new(2023, 11, 30)
|
|
|
|
travel_to destination_time do
|
|
assert_equal expected_time, Time.now
|
|
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
|
|
assert_equal expected_utc_offset, Time.now.utc_offset
|
|
|
|
assert_equal expected_datetime, DateTime.now
|
|
assert_equal expected_datetime.to_fs(:db), DateTime.now.to_fs(:db)
|
|
assert_equal expected_utc_offset, DateTime.now.utc_offset
|
|
|
|
assert_equal expected_date, Date.today
|
|
|
|
# Time.new with no args equals to Time.now
|
|
assert_equal expected_time, Time.new
|
|
assert_equal expected_time.to_fs(:db), Time.new.to_fs(:db)
|
|
assert_equal expected_utc_offset, Time.new.utc_offset
|
|
|
|
# Time.new with any args falls back to original Ruby implementation
|
|
assert_equal expected_time_in_2021, Time.new(2021)
|
|
assert_equal expected_time_in_2021.to_fs(:db), Time.new(2021).to_fs(:db)
|
|
assert_equal expected_time_in_2021.utc_offset, Time.new(2021).utc_offset
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_string_for_time_zone
|
|
with_env_tz "US/Eastern" do
|
|
with_tz_default ActiveSupport::TimeZone["UTC"] do
|
|
Time.stub(:now, Time.now) do
|
|
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
|
|
travel_to "2004-11-24 01:04:44" do
|
|
assert_equal expected_time.to_fs(:db), Time.zone.now.to_fs(:db)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_separate_class
|
|
travel_object = TravelClass.new
|
|
date1 = Date.new(2004, 11, 24)
|
|
date2 = Date.new(2005, 11, 24)
|
|
|
|
Time.stub(:now, now = Time.now) do
|
|
travel_to(date1) do
|
|
travel_object.travel_to_no_block(date2)
|
|
end
|
|
assert_equal now, Time.now
|
|
|
|
travel_to(date1) do
|
|
travel_object.travel_to_no_block(date2)
|
|
assert_equal date2, Date.today
|
|
end
|
|
assert_equal now, Time.now
|
|
|
|
travel_to(date1) do
|
|
travel_object.travel_to_block(date2)
|
|
assert_equal date1, Date.today
|
|
end
|
|
assert_equal now, Time.now
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_back
|
|
Time.stub(:now, Time.now) do
|
|
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
|
|
travel_to expected_time
|
|
assert_equal expected_time, Time.now
|
|
assert_equal expected_time, Time.new
|
|
assert_equal Date.new(2004, 11, 24), Date.today
|
|
assert_equal expected_time.to_datetime, DateTime.now
|
|
travel_back
|
|
|
|
assert_not_equal expected_time, Time.now
|
|
assert_not_equal expected_time, Time.new
|
|
assert_not_equal Date.new(2004, 11, 24), Date.today
|
|
assert_not_equal expected_time.to_datetime, DateTime.now
|
|
ensure
|
|
travel_back
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_back_with_block
|
|
Time.stub(:now, Time.now) do
|
|
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
|
|
travel_to expected_time
|
|
assert_equal expected_time, Time.now
|
|
assert_equal expected_time, Time.new
|
|
assert_equal Date.new(2004, 11, 24), Date.today
|
|
assert_equal expected_time.to_datetime, DateTime.now
|
|
|
|
travel_back do
|
|
assert_not_equal expected_time, Time.now
|
|
assert_not_equal expected_time, Time.new
|
|
assert_not_equal Date.new(2004, 11, 24), Date.today
|
|
assert_not_equal expected_time.to_datetime, DateTime.now
|
|
end
|
|
|
|
assert_equal expected_time, Time.now
|
|
assert_equal expected_time, Time.new
|
|
assert_equal Date.new(2004, 11, 24), Date.today
|
|
assert_equal expected_time.to_datetime, DateTime.now
|
|
ensure
|
|
travel_back
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_nested_calls_with_blocks
|
|
Time.stub(:now, Time.now) do
|
|
outer_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
inner_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
|
|
travel_to outer_expected_time do
|
|
e = assert_raises(RuntimeError) do
|
|
travel_to(inner_expected_time) do
|
|
# noop
|
|
end
|
|
end
|
|
assert_match(/Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing\./, e.message)
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_nested_calls
|
|
Time.stub(:now, Time.now) do
|
|
outer_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
inner_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
|
|
travel_to outer_expected_time do
|
|
assert_nothing_raised do
|
|
travel_to(inner_expected_time)
|
|
|
|
assert_equal inner_expected_time, Time.now
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_subsequent_calls
|
|
Time.stub(:now, Time.now) do
|
|
initial_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
subsequent_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
|
|
assert_nothing_raised do
|
|
travel_to initial_expected_time
|
|
travel_to subsequent_expected_time
|
|
|
|
assert_equal subsequent_expected_time, Time.now
|
|
|
|
travel_back
|
|
end
|
|
ensure
|
|
travel_back
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_to_with_usec
|
|
Time.stub(:now, Time.now) do
|
|
duration_usec = 0.1.seconds
|
|
traveled_time = Time.new(2004, 11, 24, 1, 4, 44) + duration_usec
|
|
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
|
|
assert_nothing_raised do
|
|
travel_to traveled_time
|
|
|
|
assert_equal expected_time, Time.now
|
|
|
|
travel_back
|
|
end
|
|
ensure
|
|
travel_back
|
|
end
|
|
end
|
|
|
|
def test_time_helper_with_usec_true
|
|
Time.stub(:now, Time.now) do
|
|
duration_usec = 0.1.seconds
|
|
expected_time = Time.new(2004, 11, 24, 1, 4, 44) + duration_usec
|
|
|
|
assert_nothing_raised do
|
|
travel_to expected_time, with_usec: true
|
|
|
|
assert_equal expected_time.to_f, Time.now.to_f
|
|
|
|
travel 0.5, with_usec: true
|
|
|
|
assert_equal((expected_time + 0.5).to_f, Time.now.to_f)
|
|
|
|
travel_back
|
|
end
|
|
ensure
|
|
travel_back
|
|
end
|
|
end
|
|
|
|
def test_time_helper_freeze_time_with_usec_true
|
|
# repeatedly test in case Time.now happened to actually be 0 usec
|
|
checks = 9.times.map do
|
|
freeze_time(with_usec: true) do
|
|
Time.now.usec != 0
|
|
end
|
|
end
|
|
assert_predicate checks, :any?
|
|
end
|
|
|
|
def test_time_helper_travel_with_subsequent_block
|
|
Time.stub(:now, Time.now) do
|
|
outer_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
|
|
inner_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
|
|
travel_to outer_expected_time
|
|
|
|
assert_equal outer_expected_time, Time.now
|
|
|
|
assert_nothing_raised do
|
|
travel_to(inner_expected_time) do
|
|
assert_equal inner_expected_time, Time.now
|
|
end
|
|
end
|
|
|
|
assert_equal outer_expected_time, Time.now
|
|
ensure
|
|
travel_back
|
|
end
|
|
end
|
|
|
|
def test_travel_to_will_reset_the_usec_to_avoid_mysql_rounding
|
|
Time.stub(:now, Time.now) do
|
|
travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do
|
|
assert_equal 50, Time.now.sec
|
|
assert_equal 0, Time.now.usec
|
|
assert_equal 50, DateTime.now.sec
|
|
assert_equal 0, DateTime.now.usec
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_time_helper_travel_with_time_subclass
|
|
assert_equal TimeSubclass, TimeSubclass.now.class
|
|
assert_equal DateSubclass, DateSubclass.today.class
|
|
assert_equal DateTimeSubclass, DateTimeSubclass.now.class
|
|
|
|
travel 1.day do
|
|
assert_equal TimeSubclass, TimeSubclass.now.class
|
|
assert_equal DateSubclass, DateSubclass.today.class
|
|
assert_equal DateTimeSubclass, DateTimeSubclass.now.class
|
|
assert_equal Time.now.to_s, TimeSubclass.now.to_s
|
|
assert_equal Date.today.to_s, DateSubclass.today.to_s
|
|
assert_equal DateTime.now.to_s, DateTimeSubclass.now.to_s
|
|
end
|
|
end
|
|
|
|
def test_time_helper_freeze_time
|
|
expected_time = Time.now
|
|
freeze_time
|
|
sleep(1)
|
|
|
|
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
|
|
ensure
|
|
travel_back
|
|
end
|
|
|
|
def test_time_helper_freeze_time_with_block
|
|
expected_time = Time.now
|
|
|
|
freeze_time do
|
|
sleep(1)
|
|
|
|
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
|
|
end
|
|
|
|
assert_operator expected_time.to_fs(:db), :<, Time.now.to_fs(:db)
|
|
end
|
|
|
|
def test_time_helper_unfreeze_time
|
|
assert_equal method(:travel_back), method(:unfreeze_time)
|
|
end
|
|
end
|