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:
parent
40174962e2
commit
045a2abcec
1
Gemfile
1
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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\]/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue