From 045a2abcec119399a10621f0bec2cb70783e31cc Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Mon, 24 Jul 2017 09:17:42 -0400 Subject: [PATCH] FEATURE: remove the timecop gem We should only have one way of mocking time, misuse of timecop was causing build stability issues --- Gemfile | 1 - Gemfile.lock | 2 - app/models/topic_converter.rb | 3 +- plugins/poll/lib/tasks/migrate_old_polls.rake | 3 +- .../spec/controllers/posts_controller_spec.rb | 4 +- script/require_profiler.rb | 2 +- spec/components/email/processor_spec.rb | 14 +- spec/components/email/receiver_spec.rb | 12 +- spec/components/post_creator_spec.rb | 38 ++-- spec/integration/topic_auto_close_spec.rb | 18 +- spec/jobs/dashboard_stats_spec.rb | 20 +- spec/jobs/delete_topic_spec.rb | 40 ++-- spec/jobs/grant_anniversary_badges_spec.rb | 3 +- spec/jobs/jobs_spec.rb | 14 +- spec/jobs/publish_topic_to_category_spec.rb | 11 +- spec/jobs/tl3_promotions_spec.rb | 7 +- spec/jobs/toggle_topic_closed_spec.rb | 4 +- spec/jobs/topic_reminder_spec.rb | 47 ++-- spec/models/given_daily_like_spec.rb | 33 ++- spec/models/group_spec.rb | 26 +-- spec/models/post_action_spec.rb | 73 ++++--- spec/models/report_spec.rb | 7 +- spec/models/screened_email_spec.rb | 2 +- spec/models/search_log_spec.rb | 203 +++++++++--------- spec/models/site_setting_spec.rb | 4 - spec/models/topic_converter_spec.rb | 12 +- spec/models/topic_spec.rb | 116 +++++----- spec/models/topic_timer_spec.rb | 73 +++---- spec/models/user_spec.rb | 23 +- spec/models/user_visit_spec.rb | 3 +- spec/rails_helper.rb | 25 ++- spec/services/badge_granter_spec.rb | 8 +- spec/services/post_alerter_spec.rb | 23 +- spec/services/topic_timestamp_changer_spec.rb | 50 ++--- .../shared_examples_for_stats_cacheable.rb | 8 +- 35 files changed, 459 insertions(+), 473 deletions(-) diff --git a/Gemfile b/Gemfile index 03dbe0a17bf..091bf3fd1eb 100644 --- a/Gemfile +++ b/Gemfile @@ -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 diff --git a/Gemfile.lock b/Gemfile.lock index 363c34456ce..dce01c3c166 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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 diff --git a/app/models/topic_converter.rb b/app/models/topic_converter.rb index dd5bc30559c..3ec37b314a5 100644 --- a/app/models/topic_converter.rb +++ b/app/models/topic_converter.rb @@ -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 diff --git a/plugins/poll/lib/tasks/migrate_old_polls.rake b/plugins/poll/lib/tasks/migrate_old_polls.rake index 9a551a18a65..17e5c3946c8 100644 --- a/plugins/poll/lib/tasks/migrate_old_polls.rake +++ b/plugins/poll/lib/tasks/migrate_old_polls.rake @@ -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\]/ diff --git a/plugins/poll/spec/controllers/posts_controller_spec.rb b/plugins/poll/spec/controllers/posts_controller_spec.rb index 7d1b253a2db..41bd0a42db8 100644 --- a/plugins/poll/spec/controllers/posts_controller_spec.rb +++ b/plugins/poll/spec/controllers/posts_controller_spec.rb @@ -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 diff --git a/script/require_profiler.rb b/script/require_profiler.rb index 8d760efe7cb..592f1b7082d 100644 --- a/script/require_profiler.rb +++ b/script/require_profiler.rb @@ -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 diff --git a/spec/components/email/processor_spec.rb b/spec/components/email/processor_spec.rb index a58cd26078e..73a54d9b53a 100644 --- a/spec/components/email/processor_spec.rb +++ b/spec/components/email/processor_spec.rb @@ -44,14 +44,14 @@ describe Email::Processor do Email::Processor.process!(mail2) }.to change { EmailLog.count }.by(0) - Timecop.freeze(Date.today + 1) do - key = "rejection_email:#{[from]}:email_reject_empty:#{Date.today}" - $redis.expire(key, 0) + freeze_time(Date.today + 1) - expect { - Email::Processor.process!(mail3) - }.to change { EmailLog.count }.by(1) - end + key = "rejection_email:#{[from]}:email_reject_empty:#{Date.today}" + $redis.expire(key, 0) + + expect { + Email::Processor.process!(mail3) + }.to change { EmailLog.count }.by(1) end end diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb index f595221d7ff..35d249a9707 100644 --- a/spec/components/email/receiver_spec.rb +++ b/spec/components/email/receiver_spec.rb @@ -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 - expect { process(:hard_bounce_via_verp_2) }.to raise_error(Email::Receiver::BouncedEmailError) + freeze_time 2.days.from_now - 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 { process(:hard_bounce_via_verp_2) }.to raise_error(Email::Receiver::BouncedEmailError) + + email_log_2.reload + expect(email_log_2.user.user_stat.bounce_score).to eq(4) + expect(email_log_2.bounced).to eq(true) end end diff --git a/spec/components/post_creator_spec.rb b/spec/components/post_creator_spec.rb index 49cf2daef5a..44450021121 100644 --- a/spec/components/post_creator_spec.rb +++ b/spec/components/post_creator_spec.rb @@ -287,34 +287,32 @@ 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 - PostCreator.new(topic.user, topic_id: topic.id, raw: "this is a second post").create - topic.reload + 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 - topic_status_update = TopicTimer.last - 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 + topic_status_update = TopicTimer.last + 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 it "updates topic's auto close date when it's based on last post" do - Timecop.freeze do - topic = Fabricate(:topic_timer, - based_on_last_post: true, - execute_at: Time.zone.now - 12.hours, - created_at: Time.zone.now - 24.hours - ).topic + freeze_time + topic = Fabricate(:topic_timer, + based_on_last_post: true, + execute_at: Time.zone.now - 12.hours, + created_at: Time.zone.now - 24.hours + ).topic - Fabricate(:post, topic: topic) + Fabricate(:post, topic: topic) - PostCreator.new(topic.user, topic_id: topic.id, raw: "this is a second post").create + PostCreator.new(topic.user, topic_id: topic.id, raw: "this is a second post").create - topic_status_update = TopicTimer.last - 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 + topic_status_update = TopicTimer.last + 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 diff --git a/spec/integration/topic_auto_close_spec.rb b/spec/integration/topic_auto_close_spec.rb index 75d2e07c2cd..ad4a091cd26 100644 --- a/spec/integration/topic_auto_close_spec.rb +++ b/spec/integration/topic_auto_close_spec.rb @@ -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,14 +74,14 @@ describe Topic do context 'topic is closed manually' do it 'should remove the schedule to auto-close the topic' do - Timecop.freeze do - topic_timer_id = staff_topic.public_topic_timer.id + freeze_time - staff_topic.update_status('closed', true, admin) + topic_timer_id = staff_topic.public_topic_timer.id - expect(TopicTimer.with_deleted.find(topic_timer_id).deleted_at) - .to be_within(1.second).of(Time.zone.now) - end + staff_topic.update_status('closed', true, admin) + + expect(TopicTimer.with_deleted.find(topic_timer_id).deleted_at) + .to be_within(1.second).of(Time.zone.now) end end end diff --git a/spec/jobs/dashboard_stats_spec.rb b/spec/jobs/dashboard_stats_spec.rb index 1a325f62ee3..9a339c53a87 100644 --- a/spec/jobs/dashboard_stats_spec.rb +++ b/spec/jobs/dashboard_stats_spec.rb @@ -2,17 +2,17 @@ require 'rails_helper' describe Jobs::DashboardStats do it 'caches the stats' do - Timecop.freeze do - begin - stats = AdminDashboardData.fetch_stats.to_json - cache_key = AdminDashboardData.stats_cache_key + freeze_time - expect($redis.get(cache_key)).to eq(nil) - expect(described_class.new.execute({})).to eq(stats) - expect($redis.get(cache_key)).to eq(stats) - ensure - $redis.del(cache_key) - end + begin + stats = AdminDashboardData.fetch_stats.to_json + cache_key = AdminDashboardData.stats_cache_key + + expect($redis.get(cache_key)).to eq(nil) + expect(described_class.new.execute({})).to eq(stats) + expect($redis.get(cache_key)).to eq(stats) + ensure + $redis.del(cache_key) end end end diff --git a/spec/jobs/delete_topic_spec.rb b/spec/jobs/delete_topic_spec.rb index afab1a25880..03ca8a53efa 100644 --- a/spec/jobs/delete_topic_spec.rb +++ b/spec/jobs/delete_topic_spec.rb @@ -16,30 +16,33 @@ describe Jobs::DeleteTopic do it "can delete a topic" do first_post - Timecop.freeze(2.hours.from_now) do - 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 + 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 it "should do nothing if topic is already deleted" do first_post topic.trash! - Timecop.freeze(2.hours.from_now) do - Topic.any_instance.expects(:trash!).never - described_class.new.execute(topic_timer_id: topic.public_topic_timer.id) - end + + 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 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 - described_class.new.execute(topic_timer_id: t.public_topic_timer.id) - expect(t.reload).to_not be_trashed - end + + 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 describe "user isn't authorized to delete topics" do @@ -49,10 +52,11 @@ describe Jobs::DeleteTopic do it "shouldn't delete the topic" do create_post(topic: topic) - Timecop.freeze(2.hours.from_now) do - described_class.new.execute(topic_timer_id: topic.public_topic_timer.id) - expect(topic.reload).to_not be_trashed - end + + 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 diff --git a/spec/jobs/grant_anniversary_badges_spec.rb b/spec/jobs/grant_anniversary_badges_spec.rb index a391b8c2f12..69a93dccada 100644 --- a/spec/jobs/grant_anniversary_badges_spec.rb +++ b/spec/jobs/grant_anniversary_badges_spec.rb @@ -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) diff --git a/spec/jobs/jobs_spec.rb b/spec/jobs/jobs_spec.rb index a5e6203ac35..9f200eceb24 100644 --- a/spec/jobs/jobs_spec.rb +++ b/spec/jobs/jobs_spec.rb @@ -107,17 +107,15 @@ describe Jobs do describe 'enqueue_at' do it 'calls enqueue_in for you' do - Timecop.freeze(Time.zone.now) do - Jobs.expects(:enqueue_in).with(3 * 60 * 60, :eat_lunch, {}).returns(true) - Jobs.enqueue_at(3.hours.from_now, :eat_lunch, {}) - end + freeze_time + Jobs.expects(:enqueue_in).with(3 * 60 * 60, :eat_lunch, {}).returns(true) + Jobs.enqueue_at(3.hours.from_now, :eat_lunch, {}) end it 'handles datetimes that are in the past' do - Timecop.freeze(Time.zone.now) do - Jobs.expects(:enqueue_in).with(0, :eat_lunch, {}).returns(true) - Jobs.enqueue_at(3.hours.ago, :eat_lunch, {}) - end + freeze_time + Jobs.expects(:enqueue_in).with(0, :eat_lunch, {}).returns(true) + Jobs.enqueue_at(3.hours.ago, :eat_lunch, {}) end end diff --git a/spec/jobs/publish_topic_to_category_spec.rb b/spec/jobs/publish_topic_to_category_spec.rb index 84933d2a0e6..247ccb37448 100644 --- a/spec/jobs/publish_topic_to_category_spec.rb +++ b/spec/jobs/publish_topic_to_category_spec.rb @@ -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 diff --git a/spec/jobs/tl3_promotions_spec.rb b/spec/jobs/tl3_promotions_spec.rb index 7c4aff73541..bf440918fdf 100644 --- a/spec/jobs/tl3_promotions_spec.rb +++ b/spec/jobs/tl3_promotions_spec.rb @@ -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 diff --git a/spec/jobs/toggle_topic_closed_spec.rb b/spec/jobs/toggle_topic_closed_spec.rb index e6ef2997211..2e36f8abaa8 100644 --- a/spec/jobs/toggle_topic_closed_spec.rb +++ b/spec/jobs/toggle_topic_closed_spec.rb @@ -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 diff --git a/spec/jobs/topic_reminder_spec.rb b/spec/jobs/topic_reminder_spec.rb index f79d6786ce7..518fba6fc60 100644 --- a/spec/jobs/topic_reminder_spec.rb +++ b/spec/jobs/topic_reminder_spec.rb @@ -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 - 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 + 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 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 - expect { - described_class.new.execute(topic_timer_id: topic_timer.id) - }.to_not change { Notification.count } - end + + freeze_time(1.day.from_now) + + expect { + described_class.new.execute(topic_timer_id: topic_timer.id) + }.to_not change { Notification.count } 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 - expect { - described_class.new.execute(topic_timer_id: topic_timer.id) - }.to_not change { Notification.count } - end + + freeze_time(6.hours.from_now) + + expect { + described_class.new.execute(topic_timer_id: topic_timer.id) + }.to_not change { Notification.count } end it "does nothing if topic was deleted" do topic_timer = topic.topic_timers.first topic.trash! - Timecop.freeze(1.day.from_now) do - expect { - described_class.new.execute(topic_timer_id: topic_timer.id) - }.to_not change { Notification.count } - end + + freeze_time(1.day.from_now) + + expect { + described_class.new.execute(topic_timer_id: topic_timer.id) + }.to_not change { Notification.count } end end diff --git a/spec/models/given_daily_like_spec.rb b/spec/models/given_daily_like_spec.rb index b3a86367769..0216c30b041 100644 --- a/spec/models/given_daily_like_spec.rb +++ b/spec/models/given_daily_like_spec.rb @@ -21,28 +21,27 @@ describe GivenDailyLike do it 'can be incremented and decremented' do SiteSetting.max_likes_per_day = 2 - Timecop.freeze(Date.today) do - dt = Date.today + 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) + expect(value_for(user.id, dt)).to eq(0) + expect(limit_reached_for(user.id, dt)).to eq(false) - GivenDailyLike.increment_for(user.id) - expect(value_for(user.id, dt)).to eq(1) - expect(limit_reached_for(user.id, dt)).to eq(false) + GivenDailyLike.increment_for(user.id) + expect(value_for(user.id, dt)).to eq(1) + expect(limit_reached_for(user.id, dt)).to eq(false) - GivenDailyLike.increment_for(user.id) - expect(value_for(user.id, dt)).to eq(2) - expect(limit_reached_for(user.id, dt)).to eq(true) + GivenDailyLike.increment_for(user.id) + expect(value_for(user.id, dt)).to eq(2) + expect(limit_reached_for(user.id, dt)).to eq(true) - GivenDailyLike.decrement_for(user.id) - expect(value_for(user.id, dt)).to eq(1) - expect(limit_reached_for(user.id, dt)).to eq(false) + GivenDailyLike.decrement_for(user.id) + expect(value_for(user.id, dt)).to eq(1) + expect(limit_reached_for(user.id, dt)).to eq(false) - GivenDailyLike.decrement_for(user.id) - expect(value_for(user.id, dt)).to eq(0) - expect(limit_reached_for(user.id, dt)).to eq(false) - end + GivenDailyLike.decrement_for(user.id) + expect(value_for(user.id, dt)).to eq(0) + expect(limit_reached_for(user.id, dt)).to eq(false) end end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index aa53597a608..3a53b68bd07 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -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 diff --git a/spec/models/post_action_spec.rb b/spec/models/post_action_spec.rb index 408ca8014e1..4906be462a0 100644 --- a/spec/models/post_action_spec.rb +++ b/spec/models/post_action_spec.rb @@ -178,24 +178,23 @@ describe PostAction do describe "update_counters" do it "properly updates topic counters" do - Timecop.freeze(Date.today) do - # we need this to test it - TopicUser.change(codinghorror, post.topic, posted: true) + freeze_time Date.today + # we need this to test it + TopicUser.change(codinghorror, post.topic, posted: true) - expect(value_for(moderator.id, Date.today)).to eq(0) + expect(value_for(moderator.id, Date.today)).to eq(0) - PostAction.act(moderator, post, PostActionType.types[:like]) - PostAction.act(codinghorror, second_post, PostActionType.types[:like]) + PostAction.act(moderator, post, PostActionType.types[:like]) + PostAction.act(codinghorror, second_post, PostActionType.types[:like]) - post.topic.reload - expect(post.topic.like_count).to eq(2) + post.topic.reload + expect(post.topic.like_count).to eq(2) - expect(value_for(moderator.id, Date.today)).to eq(1) + expect(value_for(moderator.id, Date.today)).to eq(1) - tu = TopicUser.get(post.topic, codinghorror) - expect(tu.liked).to be true - expect(tu.bookmarked).to be false - end + tu = TopicUser.get(post.topic, codinghorror) + expect(tu.liked).to be true + expect(tu.bookmarked).to be false end end @@ -249,33 +248,33 @@ describe PostAction do end it 'should increase the `like_count` and `like_score` when a user likes something' do - Timecop.freeze(Date.today) do - PostAction.act(codinghorror, post, PostActionType.types[:like]) - post.reload - expect(post.like_count).to eq(1) - expect(post.like_score).to eq(1) - post.topic.reload - expect(post.topic.like_count).to eq(1) - expect(value_for(codinghorror.id, Date.today)).to eq(1) + freeze_time Date.today - # When a staff member likes it - PostAction.act(moderator, post, PostActionType.types[:like]) - post.reload - expect(post.like_count).to eq(2) - expect(post.like_score).to eq(4) + PostAction.act(codinghorror, post, PostActionType.types[:like]) + post.reload + expect(post.like_count).to eq(1) + expect(post.like_score).to eq(1) + post.topic.reload + expect(post.topic.like_count).to eq(1) + expect(value_for(codinghorror.id, Date.today)).to eq(1) - # Removing likes - PostAction.remove_act(codinghorror, post, PostActionType.types[:like]) - post.reload - expect(post.like_count).to eq(1) - expect(post.like_score).to eq(3) - expect(value_for(codinghorror.id, Date.today)).to eq(0) + # When a staff member likes it + PostAction.act(moderator, post, PostActionType.types[:like]) + post.reload + expect(post.like_count).to eq(2) + expect(post.like_score).to eq(4) - PostAction.remove_act(moderator, post, PostActionType.types[:like]) - post.reload - expect(post.like_count).to eq(0) - expect(post.like_score).to eq(0) - end + # Removing likes + PostAction.remove_act(codinghorror, post, PostActionType.types[:like]) + post.reload + expect(post.like_count).to eq(1) + expect(post.like_score).to eq(3) + expect(value_for(codinghorror.id, Date.today)).to eq(0) + + PostAction.remove_act(moderator, post, PostActionType.types[:like]) + post.reload + expect(post.like_count).to eq(0) + expect(post.like_score).to eq(0) end end diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index 661cea8b2b8..c91eb0493c5 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -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 diff --git a/spec/models/screened_email_spec.rb b/spec/models/screened_email_spec.rb index 73647731585..af4e82c43da 100644 --- a/spec/models/screened_email_spec.rb +++ b/spec/models/screened_email_spec.rb @@ -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 diff --git a/spec/models/search_log_spec.rb b/spec/models/search_log_spec.rb index 63f23712fb1..34dabb0f38c 100644 --- a/spec/models/search_log_spec.rb +++ b/spec/models/search_log_spec.rb @@ -26,62 +26,59 @@ RSpec.describe SearchLog, type: :model do context "when anonymous" do it "logs and updates the search" do - Timecop.freeze do - action, log_id = SearchLog.log( - term: 'jabba', - search_type: :header, - ip_address: '192.168.0.33' - ) - expect(action).to eq(:created) - log = SearchLog.find(log_id) - expect(log.term).to eq('jabba') - expect(log.search_type).to eq(SearchLog.search_types[:header]) - expect(log.ip_address).to eq('192.168.0.33') + freeze_time + action, log_id = SearchLog.log( + term: 'jabba', + search_type: :header, + ip_address: '192.168.0.33' + ) + expect(action).to eq(:created) + log = SearchLog.find(log_id) + expect(log.term).to eq('jabba') + expect(log.search_type).to eq(SearchLog.search_types[:header]) + expect(log.ip_address).to eq('192.168.0.33') - action, updated_log_id = SearchLog.log( - term: 'jabba the hut', - search_type: :header, - ip_address: '192.168.0.33' - ) - expect(action).to eq(:updated) - expect(updated_log_id).to eq(log_id) - end + action, updated_log_id = SearchLog.log( + term: 'jabba the hut', + search_type: :header, + ip_address: '192.168.0.33' + ) + expect(action).to eq(:updated) + expect(updated_log_id).to eq(log_id) end it "creates a new search with a different prefix" do - Timecop.freeze do - action, _ = SearchLog.log( - term: 'darth', - search_type: :header, - ip_address: '127.0.0.1' - ) - expect(action).to eq(:created) + freeze_time + action, _ = SearchLog.log( + term: 'darth', + search_type: :header, + ip_address: '127.0.0.1' + ) + expect(action).to eq(:created) - action, _ = SearchLog.log( - term: 'anakin', - search_type: :header, - ip_address: '127.0.0.1' - ) - expect(action).to eq(:created) - end + action, _ = SearchLog.log( + term: 'anakin', + search_type: :header, + ip_address: '127.0.0.1' + ) + expect(action).to eq(:created) end it "creates a new search with a different ip" do - Timecop.freeze do - action, _ = SearchLog.log( - term: 'darth', - search_type: :header, - ip_address: '127.0.0.1' - ) - expect(action).to eq(:created) + freeze_time + action, _ = SearchLog.log( + term: 'darth', + search_type: :header, + ip_address: '127.0.0.1' + ) + expect(action).to eq(:created) - action, _ = SearchLog.log( - term: 'darth', - search_type: :header, - ip_address: '127.0.0.2' - ) - expect(action).to eq(:created) - end + action, _ = SearchLog.log( + term: 'darth', + search_type: :header, + ip_address: '127.0.0.2' + ) + expect(action).to eq(:created) end end @@ -89,71 +86,71 @@ RSpec.describe SearchLog, type: :model do let(:user) { Fabricate(:user) } it "logs and updates the search" do - Timecop.freeze do - action, log_id = SearchLog.log( - term: 'hello', - search_type: :full_page, - ip_address: '192.168.0.1', - user_id: user.id - ) - expect(action).to eq(:created) - log = SearchLog.find(log_id) - expect(log.term).to eq('hello') - expect(log.search_type).to eq(SearchLog.search_types[:full_page]) - expect(log.ip_address).to eq('192.168.0.1') - expect(log.user_id).to eq(user.id) + freeze_time + action, log_id = SearchLog.log( + term: 'hello', + search_type: :full_page, + ip_address: '192.168.0.1', + user_id: user.id + ) + expect(action).to eq(:created) + log = SearchLog.find(log_id) + expect(log.term).to eq('hello') + expect(log.search_type).to eq(SearchLog.search_types[:full_page]) + expect(log.ip_address).to eq('192.168.0.1') + expect(log.user_id).to eq(user.id) - action, updated_log_id = SearchLog.log( - term: 'hello dolly', - search_type: :header, - ip_address: '192.168.0.33', - user_id: user.id - ) - expect(action).to eq(:updated) - expect(updated_log_id).to eq(log_id) - end + action, updated_log_id = SearchLog.log( + term: 'hello dolly', + search_type: :header, + ip_address: '192.168.0.33', + user_id: user.id + ) + expect(action).to eq(:updated) + expect(updated_log_id).to eq(log_id) 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, - ip_address: '192.168.0.1', - user_id: user.id - ) - expect(action).to eq(:created) - end + action, _ = SearchLog.log( + term: 'hello', + search_type: :full_page, + ip_address: '192.168.0.1', + user_id: user.id + ) + expect(action).to eq(:created) + + 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 - action, _ = SearchLog.log( - term: 'hello', - search_type: :full_page, - ip_address: '192.168.0.1', - user_id: user.id - ) - expect(action).to eq(:created) + freeze_time - action, _ = SearchLog.log( - term: 'hello dolly', - search_type: :full_page, - ip_address: '192.168.0.1', - user_id: Fabricate(:user).id - ) - expect(action).to eq(:created) - end + action, _ = SearchLog.log( + term: 'hello', + search_type: :full_page, + ip_address: '192.168.0.1', + user_id: user.id + ) + expect(action).to eq(:created) + + action, _ = SearchLog.log( + term: 'hello dolly', + search_type: :full_page, + ip_address: '192.168.0.1', + user_id: Fabricate(:user).id + ) + expect(action).to eq(:created) end end diff --git a/spec/models/site_setting_spec.rb b/spec/models/site_setting_spec.rb index d1905b2c085..bef6f0237f7 100644 --- a/spec/models/site_setting_spec.rb +++ b/spec/models/site_setting_spec.rb @@ -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) diff --git a/spec/models/topic_converter_spec.rb b/spec/models/topic_converter_spec.rb index cee779633be..1c1a7c34314 100644 --- a/spec/models/topic_converter_spec.rb +++ b/spec/models/topic_converter_spec.rb @@ -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 diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index d2627fa9fbf..c93d6d3e393 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -1164,68 +1164,60 @@ 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 - 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 + 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 it 'can take a number of hours as an integer, with timezone offset' do - Timecop.freeze(now) do - 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 + 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 it 'can take a number of hours as a string' do - Timecop.freeze(now) do - 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 + 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 it 'can take a number of hours as a string, with timezone offset' do - Timecop.freeze(now) do - 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 + 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 it 'can take a number of hours as a string and can handle based on last post' do - Timecop.freeze(now) do - 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 + 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 it "can take a timestamp for a future time" do - Timecop.freeze(now) do - 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 + 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 it "can take a timestamp for a future time, with timezone offset" do - Timecop.freeze(now) do - 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 + 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 it "sets a validation error when given a timestamp in the past" do - Timecop.freeze(now) do - topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-19 5:00', {by_user: admin}) + 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 + 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 it "can take a timestamp with timezone" do - Timecop.freeze(now) do - 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 + 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 it 'sets topic status update user to given user if it is a staff or TL4 user' do @@ -1267,20 +1259,19 @@ describe Topic do end it 'updates topic status update execute_at if it was already set to close' do - Timecop.freeze(now) do - 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 + 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 it 'should allow status_type to be updated' do - Timecop.freeze do - topic_timer = closing_topic.set_or_create_timer( - TopicTimer.types[:publish_to_category], 72, by_user: admin - ) + freeze_time - expect(topic_timer.execute_at).to eq(3.days.from_now) - end + 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 it "does not update topic's topic status created_at it was already set to close" do @@ -1300,10 +1291,10 @@ describe Topic do expect(topic.reload.closed).to eq(false) - Timecop.travel(3.hours.from_now) do - TopicTimer.ensure_consistency! - expect(topic.reload.closed).to eq(true) - end + freeze_time 3.hours.from_now + + TopicTimer.ensure_consistency! + expect(topic.reload.closed).to eq(true) end end @@ -1320,14 +1311,14 @@ describe Topic do end it "can update a user's existing record" do - Timecop.freeze(now) do - reminder - expect { - topic.set_or_create_timer(TopicTimer.types[:reminder], 11, by_user: admin) - }.to_not change { TopicTimer.count } - reminder.reload - expect(reminder.execute_at).to eq(11.hours.from_now) - end + freeze_time now + + reminder + expect { + topic.set_or_create_timer(TopicTimer.types[:reminder], 11, by_user: admin) + }.to_not change { TopicTimer.count } + reminder.reload + expect(reminder.execute_at).to eq(11.hours.from_now) end end end @@ -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 diff --git a/spec/models/topic_timer_spec.rb b/spec/models/topic_timer_spec.rb index d38a939b947..d48760616e6 100644 --- a/spec/models/topic_timer_spec.rb +++ b/spec/models/topic_timer_spec.rb @@ -113,63 +113,60 @@ RSpec.describe TopicTimer, type: :model do describe 'when #execute_at value is changed' do it 'reschedules the job' do - Timecop.freeze do - topic_timer + freeze_time + topic_timer - Jobs.expects(:cancel_scheduled_job).with( - :toggle_topic_closed, topic_timer_id: topic_timer.id - ) + Jobs.expects(:cancel_scheduled_job).with( + :toggle_topic_closed, topic_timer_id: topic_timer.id + ) - Jobs.expects(:enqueue_at).with( - 3.days.from_now, :toggle_topic_closed, - topic_timer_id: topic_timer.id, - state: true - ) + Jobs.expects(:enqueue_at).with( + 3.days.from_now, :toggle_topic_closed, + topic_timer_id: topic_timer.id, + state: true + ) - topic_timer.update!(execute_at: 3.days.from_now, created_at: Time.zone.now) - end + topic_timer.update!(execute_at: 3.days.from_now, created_at: Time.zone.now) end describe 'when execute_at is smaller than the current time' do it 'should enqueue the job immediately' do - Timecop.freeze do - topic_timer + freeze_time + topic_timer - Jobs.expects(:enqueue_at).with( - Time.zone.now, :toggle_topic_closed, - topic_timer_id: topic_timer.id, - state: true - ) + Jobs.expects(:enqueue_at).with( + Time.zone.now, :toggle_topic_closed, + topic_timer_id: topic_timer.id, + state: true + ) - topic_timer.update!( - execute_at: Time.zone.now - 1.hour, - created_at: Time.zone.now - 2.hour - ) - end + topic_timer.update!( + execute_at: Time.zone.now - 1.hour, + created_at: Time.zone.now - 2.hour + ) end end end describe 'when user is changed' do it 'should update the job' do - Timecop.freeze do - topic_timer + freeze_time + topic_timer - Jobs.expects(:cancel_scheduled_job).with( - :toggle_topic_closed, topic_timer_id: topic_timer.id - ) + Jobs.expects(:cancel_scheduled_job).with( + :toggle_topic_closed, topic_timer_id: topic_timer.id + ) - admin = Fabricate(:admin) + admin = Fabricate(:admin) - Jobs.expects(:enqueue_at).with( - topic_timer.execute_at, - :toggle_topic_closed, - topic_timer_id: topic_timer.id, - state: true - ) + Jobs.expects(:enqueue_at).with( + topic_timer.execute_at, + :toggle_topic_closed, + topic_timer_id: topic_timer.id, + state: true + ) - topic_timer.update!(user: admin) - end + topic_timer.update!(user: admin) end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 18512fc017c..5d6c536b9d4 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -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]) diff --git a/spec/models/user_visit_spec.rb b/spec/models/user_visit_spec.rb index 658d1a43c2a..ccb58536a4b 100644 --- a/spec/models/user_visit_spec.rb +++ b/spec/models/user_visit_spec.rb @@ -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 diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 6354862d9e5..1956999881a 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -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") diff --git a/spec/services/badge_granter_spec.rb b/spec/services/badge_granter_spec.rb index ab4cda18ee4..053bfe9576d 100644 --- a/spec/services/badge_granter_spec.rb +++ b/spec/services/badge_granter_spec.rb @@ -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 diff --git a/spec/services/post_alerter_spec.rb b/spec/services/post_alerter_spec.rb index 3dd7334e184..b90f55c40d1 100644 --- a/spec/services/post_alerter_spec.rb +++ b/spec/services/post_alerter_spec.rb @@ -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 - post.revise(admin, {raw: 'I made another revision'}) - end + freeze_time 2.hours.from_now + post.revise(admin, {raw: 'I made another revision'}) post.revise(Fabricate(:admin), {raw: 'I made a revision'}) - Timecop.freeze(4.hours.from_now) do - post.revise(admin, {raw: 'I made another revision'}) - end + freeze_time 2.hours.from_now + post.revise(admin, {raw: 'I made another revision'}) 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 - PostAction.act(admin2, post, PostActionType.types[:like]) - end + freeze_time 1.hour.from_now + PostAction.act(admin2, post, PostActionType.types[:like]) 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 - admin4 = Fabricate(:admin) - PostAction.act(admin4, post, PostActionType.types[:like]) - end + freeze_time 2.days.from_now + + admin4 = Fabricate(:admin) + PostAction.act(admin4, post, PostActionType.types[:like]) # 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) diff --git a/spec/services/topic_timestamp_changer_spec.rb b/spec/services/topic_timestamp_changer_spec.rb index 1e9821adeb5..1cc740dab2e 100644 --- a/spec/services/topic_timestamp_changer_spec.rb +++ b/spec/services/topic_timestamp_changer_spec.rb @@ -21,26 +21,25 @@ describe TopicTimestampChanger do let(:new_timestamp) { old_timestamp - 2.day } it 'changes the timestamp of the topic and opening post' do - Timecop.freeze do - TopicTimestampChanger.new(topic: topic, timestamp: new_timestamp.to_f).change! + freeze_time + TopicTimestampChanger.new(topic: topic, timestamp: new_timestamp.to_f).change! - topic.reload - [:created_at, :updated_at, :bumped_at].each do |column| - expect(topic.public_send(column)).to be_within(1.second).of(new_timestamp) - end - - p1.reload - [:created_at, :updated_at].each do |column| - expect(p1.public_send(column)).to be_within(1.second).of(new_timestamp) - end - - p2.reload - [:created_at, :updated_at].each do |column| - expect(p2.public_send(column)).to be_within(1.second).of(new_timestamp + 1.day) - end - - expect(topic.last_posted_at).to be_within(1.second).of(p2.reload.created_at) + topic.reload + [:created_at, :updated_at, :bumped_at].each do |column| + expect(topic.public_send(column)).to be_within(1.second).of(new_timestamp) end + + p1.reload + [:created_at, :updated_at].each do |column| + expect(p1.public_send(column)).to be_within(1.second).of(new_timestamp) + end + + p2.reload + [:created_at, :updated_at].each do |column| + expect(p2.public_send(column)).to be_within(1.second).of(new_timestamp + 1.day) + end + + expect(topic.last_posted_at).to be_within(1.second).of(p2.reload.created_at) end describe 'when posts have timestamps in the future' do @@ -48,15 +47,16 @@ describe TopicTimestampChanger do 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 - p3 - TopicTimestampChanger.new(topic: topic, timestamp: new_timestamp.to_f).change! + freeze_time - p3.reload + p3 - [:created_at, :updated_at].each do |column| - expect(p3.public_send(column)).to be_within(1.second).of(new_timestamp) - end + TopicTimestampChanger.new(topic: topic, timestamp: new_timestamp.to_f).change! + + p3.reload + + [:created_at, :updated_at].each do |column| + expect(p3.public_send(column)).to be_within(1.second).of(new_timestamp) end end end diff --git a/spec/support/shared_examples_for_stats_cacheable.rb b/spec/support/shared_examples_for_stats_cacheable.rb index decaf1f78d5..ee6b7e99a55 100644 --- a/spec/support/shared_examples_for_stats_cacheable.rb +++ b/spec/support/shared_examples_for_stats_cacheable.rb @@ -11,10 +11,10 @@ shared_examples_for 'stats cachable' do end it 'returns fetches the stats if stats has not been cached' do - Timecop.freeze do - $redis.del(described_class.stats_cache_key) - expect(described_class.fetch_cached_stats).to eq(JSON.parse(described_class.fetch_stats.to_json)) - end + 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