FEATURE: remove the timecop gem

We should only have one way of mocking time, misuse of timecop
was causing build stability issues
This commit is contained in:
Sam Saffron 2017-07-24 09:17:42 -04:00 committed by Sam
parent 40174962e2
commit 045a2abcec
35 changed files with 459 additions and 473 deletions

View File

@ -122,7 +122,6 @@ group :test do
gem 'webmock', require: false
gem 'fakeweb', '~> 1.3.0', require: false
gem 'minitest', require: false
gem 'timecop'
# TODO: Remove once we upgrade to Rails 5.
gem 'test_after_commit'
end

View File

@ -363,7 +363,6 @@ GEM
thor (0.19.4)
thread_safe (0.3.6)
tilt (2.0.7)
timecop (0.8.1)
trollop (2.1.2)
tzinfo (1.2.3)
thread_safe (~> 0.1)
@ -476,7 +475,6 @@ DEPENDENCIES
test_after_commit
thor
tilt
timecop
uglifier
unf
unicorn

View File

@ -17,7 +17,8 @@ class TopicConverter
else
Category.where(read_restricted: false)
.where.not(id: SiteSetting.uncategorized_category_id)
.first.id
.order('id asc')
.pluck(:id).first
end
@topic.archetype = Archetype.default

View File

@ -25,7 +25,6 @@ end
desc "Migrate old polls to new syntax"
task "poll:migrate_old_polls" => :environment do
require "timecop"
# iterate over all polls
PluginStoreRow.where(plugin_name: "poll")
.where("key LIKE 'poll_options_%'")
@ -39,7 +38,7 @@ task "poll:migrate_old_polls" => :environment do
# skip if already migrated
next if post.custom_fields.include?("polls")
# go back in time
Timecop.freeze(post.created_at + 1.minute) do
freeze_time(post.created_at + 1.minute) do
raw = post.raw.gsub(/\n\n([ ]*[-\*\+] )/, "\n\\1") + "\n\n"
# fix the RAW when needed
if raw !~ /\[poll\]/

View File

@ -92,7 +92,7 @@ describe PostsController do
describe "within the first 5 minutes" do
let(:post_id) do
Timecop.freeze(4.minutes.ago) do
freeze_time(4.minutes.ago) do
xhr :post, :create, { title: title, raw: "[poll]\n- A\n- B\n[/poll]" }
::JSON.parse(response.body)["id"]
end
@ -122,7 +122,7 @@ describe PostsController do
let(:updated) { "before\n\n[poll]\n- A\n- B\n[/poll]\n\nafter" }
let(:post_id) do
Timecop.freeze(6.minutes.ago) do
freeze_time(6.minutes.ago) do
xhr :post, :create, { title: title, raw: poll }
::JSON.parse(response.body)["id"]
end

View File

@ -115,7 +115,7 @@ end
RequireProfiler.profile do
Bundler.definition.dependencies.each do |dep|
begin
require dep.name unless dep.name =~ /timecop/
require dep.name
rescue Exception
# don't care
end

View File

@ -44,7 +44,8 @@ describe Email::Processor do
Email::Processor.process!(mail2)
}.to change { EmailLog.count }.by(0)
Timecop.freeze(Date.today + 1) do
freeze_time(Date.today + 1)
key = "rejection_email:#{[from]}:email_reject_empty:#{Date.today}"
$redis.expire(key, 0)
@ -53,7 +54,6 @@ describe Email::Processor do
}.to change { EmailLog.count }.by(1)
end
end
end
context "unrecognized error" do

View File

@ -97,13 +97,13 @@ describe Email::Receiver do
expect(email_log.bounced).to eq(true)
expect(email_log.user.user_stat.bounce_score).to eq(2)
Timecop.freeze(2.days.from_now) do
freeze_time 2.days.from_now
expect { process(:hard_bounce_via_verp_2) }.to raise_error(Email::Receiver::BouncedEmailError)
email_log_2.reload
expect(email_log_2.bounced).to eq(true)
expect(email_log_2.user.user_stat.bounce_score).to eq(4)
end
expect(email_log_2.bounced).to eq(true)
end
end

View File

@ -287,9 +287,9 @@ describe PostCreator do
end
it "doesn't update topic's auto close when it's not based on last post" do
Timecop.freeze do
topic = Fabricate(:topic).set_or_create_timer(TopicTimer.types[:close], 12)
freeze_time
topic = Fabricate(:topic).set_or_create_timer(TopicTimer.types[:close], 12)
PostCreator.new(topic.user, topic_id: topic.id, raw: "this is a second post").create
topic.reload
@ -297,10 +297,9 @@ describe PostCreator do
expect(topic_status_update.execute_at).to be_within(1.second).of(Time.zone.now + 12.hours)
expect(topic_status_update.created_at).to be_within(1.second).of(Time.zone.now)
end
end
it "updates topic's auto close date when it's based on last post" do
Timecop.freeze do
freeze_time
topic = Fabricate(:topic_timer,
based_on_last_post: true,
execute_at: Time.zone.now - 12.hours,
@ -315,7 +314,6 @@ describe PostCreator do
expect(topic_status_update.execute_at).to be_within(1.second).of(Time.zone.now + 12.hours)
expect(topic_status_update.created_at).to be_within(1.second).of(Time.zone.now)
end
end
end

View File

@ -33,11 +33,7 @@ describe Topic do
context 'jobs may be queued' do
before do
SiteSetting.queue_jobs = true
Timecop.freeze(Time.zone.now)
end
after do
Timecop.return
freeze_time
end
context 'category has a default auto-close' do
@ -78,7 +74,8 @@ describe Topic do
context 'topic is closed manually' do
it 'should remove the schedule to auto-close the topic' do
Timecop.freeze do
freeze_time
topic_timer_id = staff_topic.public_topic_timer.id
staff_topic.update_status('closed', true, admin)
@ -88,7 +85,6 @@ describe Topic do
end
end
end
end
context 'topic was created by a non-staff user' do
let(:regular_user) { Fabricate(:user) }

View File

@ -2,7 +2,8 @@ require 'rails_helper'
describe Jobs::DashboardStats do
it 'caches the stats' do
Timecop.freeze do
freeze_time
begin
stats = AdminDashboardData.fetch_stats.to_json
cache_key = AdminDashboardData.stats_cache_key
@ -14,5 +15,4 @@ describe Jobs::DashboardStats do
$redis.del(cache_key)
end
end
end
end

View File

@ -16,31 +16,34 @@ describe Jobs::DeleteTopic do
it "can delete a topic" do
first_post
Timecop.freeze(2.hours.from_now) do
freeze_time (2.hours.from_now)
described_class.new.execute(topic_timer_id: topic.public_topic_timer.id)
expect(topic.reload).to be_trashed
expect(first_post.reload).to be_trashed
expect(topic.reload.public_topic_timer).to eq(nil)
end
end
it "should do nothing if topic is already deleted" do
first_post
topic.trash!
Timecop.freeze(2.hours.from_now) do
freeze_time 2.hours.from_now
Topic.any_instance.expects(:trash!).never
described_class.new.execute(topic_timer_id: topic.public_topic_timer.id)
end
end
it "should do nothing if it's too early" do
t = Fabricate(:topic_timer, user: admin, execute_at: 5.hours.from_now).topic
create_post(topic: t)
Timecop.freeze(4.hours.from_now) do
freeze_time 4.hours.from_now
described_class.new.execute(topic_timer_id: t.public_topic_timer.id)
expect(t.reload).to_not be_trashed
end
end
describe "user isn't authorized to delete topics" do
let(:topic) {
@ -49,11 +52,12 @@ describe Jobs::DeleteTopic do
it "shouldn't delete the topic" do
create_post(topic: topic)
Timecop.freeze(2.hours.from_now) do
freeze_time 2.hours.from_now
described_class.new.execute(topic_timer_id: topic.public_topic_timer.id)
expect(topic.reload).to_not be_trashed
end
end
end
end

View File

@ -102,9 +102,10 @@ describe Jobs::GrantAnniversaryBadges do
user = Fabricate(:user, created_at: 800.days.ago)
Fabricate(:post, user: user, created_at: 450.days.ago)
Timecop.freeze(400.days.ago) do
freeze_time(400.days.ago) do
granter.execute({})
end
badge = user.user_badges.where(badge_id: Badge::Anniversary)
expect(badge.count).to eq(1)

View File

@ -107,18 +107,16 @@ describe Jobs do
describe 'enqueue_at' do
it 'calls enqueue_in for you' do
Timecop.freeze(Time.zone.now) do
freeze_time
Jobs.expects(:enqueue_in).with(3 * 60 * 60, :eat_lunch, {}).returns(true)
Jobs.enqueue_at(3.hours.from_now, :eat_lunch, {})
end
end
it 'handles datetimes that are in the past' do
Timecop.freeze(Time.zone.now) do
freeze_time
Jobs.expects(:enqueue_in).with(0, :eat_lunch, {}).returns(true)
Jobs.enqueue_at(3.hours.ago, :eat_lunch, {})
end
end
end
end

View File

@ -29,7 +29,10 @@ RSpec.describe Jobs::PublishTopicToCategory do
describe 'when topic has been deleted' do
it 'should not publish the topic to the new category' do
Timecop.travel(1.hour.ago) { topic }
freeze_time 1.hour.ago
topic
freeze_time 1.hour.from_now
topic.trash!
described_class.new.execute(topic_timer_id: topic.public_topic_timer.id)
@ -41,7 +44,9 @@ RSpec.describe Jobs::PublishTopicToCategory do
end
it 'should publish the topic to the new category' do
Timecop.travel(1.hour.ago) { topic.update!(visible: false) }
freeze_time 1.hour.ago do
topic.update!(visible: false)
end
message = MessageBus.track_publish do
described_class.new.execute(topic_timer_id: topic.public_topic_timer.id)
@ -62,7 +67,7 @@ RSpec.describe Jobs::PublishTopicToCategory do
describe 'when topic is a private message' do
before do
Timecop.travel(1.hour.ago) do
freeze_time 1.hour.ago do
expect { topic.convert_to_private_message(Discourse.system_user) }
.to change { topic.private_message? }.to(true)
end

View File

@ -33,7 +33,8 @@ describe Jobs::Tl3Promotions do
it "demotes if was promoted more than X days ago" do
user = nil
Timecop.freeze(4.days.ago) do
freeze_time 4.days.ago do
user = create_leader_user
end
@ -45,7 +46,7 @@ describe Jobs::Tl3Promotions do
it "doesn't demote if user was promoted recently" do
user = nil
Timecop.freeze(1.day.ago) do
freeze_time 1.day.ago do
user = create_leader_user
end
@ -57,7 +58,7 @@ describe Jobs::Tl3Promotions do
it "doesn't demote if user hasn't lost requirements (low water mark)" do
user = nil
Timecop.freeze(4.days.ago) do
freeze_time(4.days.ago) do
user = create_leader_user
end

View File

@ -14,7 +14,7 @@ describe Jobs::ToggleTopicClosed do
it 'should be able to close a topic' do
topic
Timecop.travel(1.hour.from_now) do
freeze_time(1.hour.from_now) do
described_class.new.execute(
topic_timer_id: topic.public_topic_timer.id,
state: true
@ -31,7 +31,7 @@ describe Jobs::ToggleTopicClosed do
it 'should be able to open a topic' do
topic.update!(closed: true)
Timecop.travel(1.hour.from_now) do
freeze_time(1.hour.from_now) do
described_class.new.execute(
topic_timer_id: topic.public_topic_timer.id,
state: false

View File

@ -16,43 +16,46 @@ describe Jobs::TopicReminder do
it "should be able to create a reminder" do
topic_timer = topic.topic_timers.first
Timecop.freeze(1.day.from_now) do
freeze_time 1.day.from_now
expect {
described_class.new.execute(topic_timer_id: topic_timer.id)
}.to change { Notification.count }.by(1)
expect( admin.notifications.where(notification_type: Notification.types[:topic_reminder]).first&.topic_id ).to eq(topic.id)
expect( TopicTimer.where(id: topic_timer.id).first ).to be_nil
end
end
it "does nothing if it was trashed before the scheduled time" do
topic_timer = topic.topic_timers.first
topic_timer.trash!(Discourse.system_user)
Timecop.freeze(1.day.from_now) do
freeze_time(1.day.from_now)
expect {
described_class.new.execute(topic_timer_id: topic_timer.id)
}.to_not change { Notification.count }
end
end
it "does nothing if job runs too early" do
topic_timer = topic.topic_timers.first
topic_timer.update_attribute(:execute_at, 8.hours.from_now)
Timecop.freeze(6.hours.from_now) do
freeze_time(6.hours.from_now)
expect {
described_class.new.execute(topic_timer_id: topic_timer.id)
}.to_not change { Notification.count }
end
end
it "does nothing if topic was deleted" do
topic_timer = topic.topic_timers.first
topic.trash!
Timecop.freeze(1.day.from_now) do
freeze_time(1.day.from_now)
expect {
described_class.new.execute(topic_timer_id: topic_timer.id)
}.to_not change { Notification.count }
end
end
end

View File

@ -21,8 +21,8 @@ describe GivenDailyLike do
it 'can be incremented and decremented' do
SiteSetting.max_likes_per_day = 2
Timecop.freeze(Date.today) do
dt = Date.today
freeze_time dt
expect(value_for(user.id, dt)).to eq(0)
expect(limit_reached_for(user.id, dt)).to eq(false)
@ -43,7 +43,6 @@ describe GivenDailyLike do
expect(value_for(user.id, dt)).to eq(0)
expect(limit_reached_for(user.id, dt)).to eq(false)
end
end
end

View File

@ -100,15 +100,15 @@ describe Group do
end
def real_admins
Group[:admins].user_ids - [-1]
Group[:admins].user_ids.reject{|id| id < 0}
end
def real_moderators
Group[:moderators].user_ids - [-1]
Group[:moderators].user_ids.reject{|id| id < 0}
end
def real_staff
Group[:staff].user_ids - [-1]
Group[:staff].user_ids.reject{|id| id < 0}
end
it "Correctly handles primary groups" do
@ -307,11 +307,11 @@ describe Group do
user2 = Fabricate(:coding_horror)
user2.change_trust_level!(TrustLevel[3])
expect(Group[:trust_level_2].user_ids.sort).to eq [-1, user.id, user2.id].sort
expect(Group[:trust_level_2].user_ids.sort.reject{|id| id < -1}).to eq [-1, user.id, user2.id].sort
end
it "Correctly updates all automatic groups upon request" do
Fabricate(:admin)
admin = Fabricate(:admin)
user = Fabricate(:user)
user.change_trust_level!(TrustLevel[2])
@ -323,22 +323,22 @@ describe Group do
expect(groups.count).to eq Group::AUTO_GROUPS.count
g = groups.find{|grp| grp.id == Group::AUTO_GROUPS[:admins]}
expect(g.users.count).to eq 2
expect(g.user_count).to eq 2
expect(g.users.count).to eq(g.user_count)
expect(g.users.pluck(:id).sort.reject{|id| id < -1}).to eq([-1, admin.id])
g = groups.find{|grp| grp.id == Group::AUTO_GROUPS[:staff]}
expect(g.users.count).to eq 2
expect(g.user_count).to eq 2
expect(g.users.count).to eq (g.user_count)
expect(g.users.pluck(:id).sort.reject{|id| id < -1}).to eq([-1, admin.id])
g = groups.find{|grp| grp.id == Group::AUTO_GROUPS[:trust_level_1]}
# admin, system and user
expect(g.users.count).to eq 3
expect(g.user_count).to eq 3
expect(g.users.count).to eq g.user_count
expect(g.users.where('users.id > -2').count).to eq 3
g = groups.find{|grp| grp.id == Group::AUTO_GROUPS[:trust_level_2]}
# system and user
expect(g.users.count).to eq 2
expect(g.user_count).to eq 2
expect(g.users.count).to eq g.user_count
expect(g.users.where('users.id > -2').count).to eq 2
end

View File

@ -178,7 +178,7 @@ describe PostAction do
describe "update_counters" do
it "properly updates topic counters" do
Timecop.freeze(Date.today) do
freeze_time Date.today
# we need this to test it
TopicUser.change(codinghorror, post.topic, posted: true)
@ -196,7 +196,6 @@ describe PostAction do
expect(tu.liked).to be true
expect(tu.bookmarked).to be false
end
end
end
@ -249,7 +248,8 @@ describe PostAction do
end
it 'should increase the `like_count` and `like_score` when a user likes something' do
Timecop.freeze(Date.today) do
freeze_time Date.today
PostAction.act(codinghorror, post, PostActionType.types[:like])
post.reload
expect(post.like_count).to eq(1)
@ -277,7 +277,6 @@ describe PostAction do
expect(post.like_score).to eq(0)
end
end
end
describe "undo/redo repeatedly" do
it "doesn't create a second action for the same user/type" do

View File

@ -40,7 +40,7 @@ describe Report do
context "with #{pluralized}" do
before(:each) do
Timecop.freeze
freeze_time
fabricator = case arg
when :signup
:user
@ -57,7 +57,6 @@ describe Report do
Fabricate(fabricator, created_at: 30.days.ago)
Fabricate(fabricator, created_at: 35.days.ago)
end
after(:each) { Timecop.return }
context 'returns a report with data'
it "returns today's data" do
@ -87,15 +86,13 @@ describe Report do
context "with #{request_type}" do
before(:each) do
Timecop.freeze
freeze_time
ApplicationRequest.create(date: 35.days.ago.to_time, req_type: ApplicationRequest.req_types[request_type.to_s], count: 35)
ApplicationRequest.create(date: 7.days.ago.to_time, req_type: ApplicationRequest.req_types[request_type.to_s], count: 8)
ApplicationRequest.create(date: Date.today.to_time, req_type: ApplicationRequest.req_types[request_type.to_s], count: 1)
ApplicationRequest.create(date: 1.day.ago.to_time, req_type: ApplicationRequest.req_types[request_type.to_s], count: 2)
ApplicationRequest.create(date: 2.days.ago.to_time, req_type: ApplicationRequest.req_types[request_type.to_s], count: 3)
end
after(:each) { Timecop.return }
context 'returns a report with data' do
it "returns expected number of recoords" do

View File

@ -78,7 +78,7 @@ describe ScreenedEmail do
shared_examples "when a ScreenedEmail record matches" do
it "updates statistics" do
Timecop.freeze(Time.zone.now) do
freeze_time(Time.zone.now) do
expect { subject }.to change { screened_email.reload.match_count }.by(1)
expect(screened_email.last_match_at).to be_within_one_second_of(Time.zone.now)
end

View File

@ -26,7 +26,7 @@ RSpec.describe SearchLog, type: :model do
context "when anonymous" do
it "logs and updates the search" do
Timecop.freeze do
freeze_time
action, log_id = SearchLog.log(
term: 'jabba',
search_type: :header,
@ -46,10 +46,9 @@ RSpec.describe SearchLog, type: :model do
expect(action).to eq(:updated)
expect(updated_log_id).to eq(log_id)
end
end
it "creates a new search with a different prefix" do
Timecop.freeze do
freeze_time
action, _ = SearchLog.log(
term: 'darth',
search_type: :header,
@ -64,10 +63,9 @@ RSpec.describe SearchLog, type: :model do
)
expect(action).to eq(:created)
end
end
it "creates a new search with a different ip" do
Timecop.freeze do
freeze_time
action, _ = SearchLog.log(
term: 'darth',
search_type: :header,
@ -83,13 +81,12 @@ RSpec.describe SearchLog, type: :model do
expect(action).to eq(:created)
end
end
end
context "when logged in" do
let(:user) { Fabricate(:user) }
it "logs and updates the search" do
Timecop.freeze do
freeze_time
action, log_id = SearchLog.log(
term: 'hello',
search_type: :full_page,
@ -112,20 +109,10 @@ RSpec.describe SearchLog, type: :model do
expect(action).to eq(:updated)
expect(updated_log_id).to eq(log_id)
end
end
it "logs again if time has passed" do
Timecop.freeze(10.minutes.ago) do
action, _ = SearchLog.log(
term: 'hello',
search_type: :full_page,
ip_address: '192.168.0.1',
user_id: user.id
)
expect(action).to eq(:created)
end
freeze_time(10.minutes.ago)
Timecop.freeze do
action, _ = SearchLog.log(
term: 'hello',
search_type: :full_page,
@ -133,11 +120,22 @@ RSpec.describe SearchLog, type: :model do
user_id: user.id
)
expect(action).to eq(:created)
end
freeze_time(10.minutes.from_now)
action, _ = SearchLog.log(
term: 'hello',
search_type: :full_page,
ip_address: '192.168.0.1',
user_id: user.id
)
expect(action).to eq(:created)
end
it "logs again with a different user" do
Timecop.freeze do
freeze_time
action, _ = SearchLog.log(
term: 'hello',
search_type: :full_page,
@ -154,7 +152,6 @@ RSpec.describe SearchLog, type: :model do
)
expect(action).to eq(:created)
end
end
end
end

View File

@ -128,10 +128,6 @@ describe SiteSetting do
SiteSetting.force_https = true
end
after do
SiteSetting.force_https = false
end
describe '#use_https' do
it 'should act as a proxy to the new methods' do
expect(SiteSetting.use_https).to eq(true)

View File

@ -11,7 +11,7 @@ describe TopicConverter do
context 'success' do
it "converts private message to regular topic" do
SiteSetting.allow_uncategorized_topics = true
topic = described_class.new(private_message, admin).convert_to_public_topic
topic = TopicConverter.new(private_message, admin).convert_to_public_topic
topic.reload
expect(topic).to be_valid
@ -26,18 +26,22 @@ describe TopicConverter do
end
it 'should convert private message into the right category' do
topic = described_class.new(private_message, admin).convert_to_public_topic
topic = TopicConverter.new(private_message, admin).convert_to_public_topic
topic.reload
expect(topic).to be_valid
expect(topic.archetype).to eq("regular")
expect(topic.category_id).to eq(category.id)
first_category = Category.where.not(id: SiteSetting.uncategorized_category_id)
.where(read_restricted: false).order('id asc').first
expect(topic.category_id).to eq(first_category.id)
end
end
describe 'when a custom category_id is given' do
it 'should convert private message into the right category' do
topic = described_class.new(private_message, admin).convert_to_public_topic(category.id)
topic = TopicConverter.new(private_message, admin).convert_to_public_topic(category.id)
expect(topic.reload.category).to eq(category)
end

View File

@ -1164,69 +1164,61 @@ describe Topic do
before { Discourse.stubs(:system_user).returns(admin) }
it 'can take a number of hours as an integer' do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], 72, by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(3.days.from_now)
end
end
it 'can take a number of hours as an integer, with timezone offset' do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], 72, {by_user: admin, timezone_offset: 240})
expect(topic.topic_timers.first.execute_at).to eq(3.days.from_now)
end
end
it 'can take a number of hours as a string' do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '18', by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(18.hours.from_now)
end
end
it 'can take a number of hours as a string, with timezone offset' do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '18', {by_user: admin, timezone_offset: 240})
expect(topic.topic_timers.first.execute_at).to eq(18.hours.from_now)
end
end
it 'can take a number of hours as a string and can handle based on last post' do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '18', {by_user: admin, based_on_last_post: true})
expect(topic.topic_timers.first.execute_at).to eq(18.hours.from_now)
end
end
it "can take a timestamp for a future time" do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-22 5:00', {by_user: admin})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,22,5,0))
end
end
it "can take a timestamp for a future time, with timezone offset" do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-22 5:00', {by_user: admin, timezone_offset: 240})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,22,9,0))
end
end
it "sets a validation error when given a timestamp in the past" do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-19 5:00', {by_user: admin})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,19,5,0))
expect(topic.topic_timers.first.errors[:execute_at]).to be_present
end
end
it "can take a timestamp with timezone" do
Timecop.freeze(now) do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-25T01:35:00-08:00', {by_user: admin})
expect(topic.topic_timers.first.execute_at).to eq(Time.utc(2013,11,25,9,35))
end
end
it 'sets topic status update user to given user if it is a staff or TL4 user' do
topic.set_or_create_timer(TopicTimer.types[:close], 3, {by_user: admin})
@ -1267,21 +1259,20 @@ describe Topic do
end
it 'updates topic status update execute_at if it was already set to close' do
Timecop.freeze(now) do
freeze_time now
closing_topic.set_or_create_timer(TopicTimer.types[:close], 48)
expect(closing_topic.reload.public_topic_timer.execute_at).to eq(2.days.from_now)
end
end
it 'should allow status_type to be updated' do
Timecop.freeze do
freeze_time
topic_timer = closing_topic.set_or_create_timer(
TopicTimer.types[:publish_to_category], 72, by_user: admin
)
expect(topic_timer.execute_at).to eq(3.days.from_now)
end
end
it "does not update topic's topic status created_at it was already set to close" do
expect{
@ -1300,12 +1291,12 @@ describe Topic do
expect(topic.reload.closed).to eq(false)
Timecop.travel(3.hours.from_now) do
freeze_time 3.hours.from_now
TopicTimer.ensure_consistency!
expect(topic.reload.closed).to eq(true)
end
end
end
describe "private status type" do
let(:topic) { Fabricate(:topic) }
@ -1320,7 +1311,8 @@ describe Topic do
end
it "can update a user's existing record" do
Timecop.freeze(now) do
freeze_time now
reminder
expect {
topic.set_or_create_timer(TopicTimer.types[:reminder], 11, by_user: admin)
@ -1330,7 +1322,6 @@ describe Topic do
end
end
end
end
describe 'for_digest' do
let(:user) { Fabricate.build(:user) }
@ -1510,16 +1501,15 @@ describe Topic do
describe '#listable_count_per_day' do
before(:each) do
Timecop.freeze
freeze_time
Fabricate(:topic)
Fabricate(:topic, created_at: 1.day.ago)
Fabricate(:topic, created_at: 1.day.ago)
Fabricate(:topic, created_at: 2.days.ago)
Fabricate(:topic, created_at: 4.days.ago)
end
after(:each) do
Timecop.return
end
let(:listable_topics_count_per_day) { {1.day.ago.to_date => 2, 2.days.ago.to_date => 1, Time.now.utc.to_date => 1 } }
it 'collect closed interval listable topics count' do

View File

@ -113,7 +113,7 @@ RSpec.describe TopicTimer, type: :model do
describe 'when #execute_at value is changed' do
it 'reschedules the job' do
Timecop.freeze do
freeze_time
topic_timer
Jobs.expects(:cancel_scheduled_job).with(
@ -128,11 +128,10 @@ RSpec.describe TopicTimer, type: :model do
topic_timer.update!(execute_at: 3.days.from_now, created_at: Time.zone.now)
end
end
describe 'when execute_at is smaller than the current time' do
it 'should enqueue the job immediately' do
Timecop.freeze do
freeze_time
topic_timer
Jobs.expects(:enqueue_at).with(
@ -148,11 +147,10 @@ RSpec.describe TopicTimer, type: :model do
end
end
end
end
describe 'when user is changed' do
it 'should update the job' do
Timecop.freeze do
freeze_time
topic_timer
Jobs.expects(:cancel_scheduled_job).with(
@ -171,7 +169,6 @@ RSpec.describe TopicTimer, type: :model do
topic_timer.update!(user: admin)
end
end
end
describe 'when a open topic status update is created for an open topic' do
let(:topic) { Fabricate(:topic, closed: false) }

View File

@ -31,14 +31,13 @@ describe User do
describe '#count_by_signup_date' do
before(:each) do
User.destroy_all
Timecop.freeze
freeze_time
Fabricate(:user)
Fabricate(:user, created_at: 1.day.ago)
Fabricate(:user, created_at: 1.day.ago)
Fabricate(:user, created_at: 2.days.ago)
Fabricate(:user, created_at: 4.days.ago)
end
after(:each) { Timecop.return }
let(:signups_by_day) { {1.day.ago.to_date => 2, 2.days.ago.to_date => 1, Time.now.utc.to_date => 1} }
it 'collect closed interval signups' do
@ -716,14 +715,10 @@ describe User do
let!(:date) { Time.zone.now }
before do
Timecop.freeze(date)
freeze_time date
user.update_last_seen!
end
after do
Timecop.return
end
it "updates last_seen_at" do
expect(user.last_seen_at).to be_within_one_second_of(date)
end
@ -740,16 +735,12 @@ describe User do
context "called twice" do
before do
Timecop.freeze(date)
freeze_time date
user.update_last_seen!
user.update_last_seen!
user.reload
end
after do
Timecop.return
end
it "doesn't increase days_visited twice" do
expect(user.user_stat.days_visited).to eq(1)
end
@ -760,14 +751,10 @@ describe User do
let!(:future_date) { 3.days.from_now }
before do
Timecop.freeze(future_date)
freeze_time future_date
user.update_last_seen!
end
after do
Timecop.return
end
it "should log a second visited_at record when we log an update later" do
expect(user.user_visits.count).to eq(2)
end
@ -1498,7 +1485,7 @@ describe User do
describe '.human_users' do
it 'should only return users with a positive primary key' do
Fabricate(:user, id: -2)
Fabricate(:user, id: -1979)
user = Fabricate(:user)
expect(User.human_users).to eq([user])

View File

@ -23,14 +23,13 @@ describe UserVisit do
describe '#by_day' do
before(:each) do
Timecop.freeze
freeze_time
user.user_visits.create(visited_at: Time.zone.now)
user.user_visits.create(visited_at: 1.day.ago)
other_user.user_visits.create(visited_at: 1.day.ago)
user.user_visits.create(visited_at: 2.days.ago)
user.user_visits.create(visited_at: 4.days.ago)
end
after(:each) { Timecop.return }
let(:visits_by_day) { {1.day.ago.to_date => 2, 2.days.ago.to_date => 1, Time.zone.now.to_date => 1 } }
it 'collect closed interval visits' do

View File

@ -142,16 +142,39 @@ Spork.prefork do
end
class TrackTimeStub
def self.stubbed
false
end
end
def freeze_time(now=Time.now)
datetime = DateTime.parse(now.to_s)
time = Time.parse(now.to_s)
if block_given?
raise "Don't use a block with freeze_time"
raise "nested freeze time not supported" if TrackTimeStub.stubbed
end
DateTime.stubs(:now).returns(datetime)
Time.stubs(:now).returns(time)
Date.stubs(:today).returns(datetime.to_date)
TrackTimeStub.stubs(:stubbed).returns(true)
if block_given?
begin
yield
ensure
unfreeze_time
end
end
end
def unfreeze_time
DateTime.unstub(:now)
Time.unstub(:now)
Date.unstub(:today)
TrackTimeStub.unstub(:stubbed)
end
def file_from_fixtures(filename, directory="images")

View File

@ -145,13 +145,11 @@ describe BadgeGranter do
end
it 'sets granted_at' do
time = Time.zone.now
Timecop.freeze time
time = 1.day.ago
freeze_time time
user_badge = BadgeGranter.grant(badge, user)
expect(user_badge.granted_at).to eq(time)
Timecop.return
expect(user_badge.granted_at).to be_within(1.second).of(time)
end
it 'sets granted_by if the option is present' do

View File

@ -86,15 +86,13 @@ describe PostAlerter do
post.revise(admin, {raw: 'I made a revision'})
# skip this notification cause we already notified on a similar edit
Timecop.freeze(2.hours.from_now) do
freeze_time 2.hours.from_now
post.revise(admin, {raw: 'I made another revision'})
end
post.revise(Fabricate(:admin), {raw: 'I made a revision'})
Timecop.freeze(4.hours.from_now) do
freeze_time 2.hours.from_now
post.revise(admin, {raw: 'I made another revision'})
end
expect(Notification.where(post_number: 1, topic_id: post.topic_id).count).to eq(3)
end
@ -147,9 +145,8 @@ describe PostAlerter do
admin2 = Fabricate(:admin)
# Travel 1 hour in time to test that order post_actions by `created_at`
Timecop.freeze(1.hour.from_now) do
freeze_time 1.hour.from_now
PostAction.act(admin2, post, PostActionType.types[:like])
end
expect(Notification.where(post_number: 1, topic_id: post.topic_id).count)
.to eq(1)
@ -187,10 +184,10 @@ describe PostAlerter do
admin3 = Fabricate(:admin)
PostAction.act(admin3, post, PostActionType.types[:like])
Timecop.freeze(2.days.from_now) do
freeze_time 2.days.from_now
admin4 = Fabricate(:admin)
PostAction.act(admin4, post, PostActionType.types[:like])
end
# first happend within the same day, no need to notify
expect(Notification.where(post_number: 1, topic_id: post.topic_id).count).to eq(2)

View File

@ -21,7 +21,7 @@ describe TopicTimestampChanger do
let(:new_timestamp) { old_timestamp - 2.day }
it 'changes the timestamp of the topic and opening post' do
Timecop.freeze do
freeze_time
TopicTimestampChanger.new(topic: topic, timestamp: new_timestamp.to_f).change!
topic.reload
@ -41,15 +41,16 @@ describe TopicTimestampChanger do
expect(topic.last_posted_at).to be_within(1.second).of(p2.reload.created_at)
end
end
describe 'when posts have timestamps in the future' do
let(:new_timestamp) { Time.zone.now }
let(:p3) { Fabricate(:post, topic: topic, created_at: new_timestamp + 3.day) }
it 'should set the new timestamp as the default timestamp' do
Timecop.freeze do
freeze_time
p3
TopicTimestampChanger.new(topic: topic, timestamp: new_timestamp.to_f).change!
p3.reload
@ -60,7 +61,6 @@ describe TopicTimestampChanger do
end
end
end
end
it 'deletes the stats cache' do
$redis.set AdminDashboardData.stats_cache_key, "X"

View File

@ -11,12 +11,12 @@ shared_examples_for 'stats cachable' do
end
it 'returns fetches the stats if stats has not been cached' do
Timecop.freeze do
freeze_time
$redis.del(described_class.stats_cache_key)
expect(described_class.fetch_cached_stats).to eq(JSON.parse(described_class.fetch_stats.to_json))
end
end
end
describe 'fetch_stats' do
it 'has not been implemented' do