2019-04-29 19:27:42 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2015-10-11 04:41:23 -05:00
|
|
|
require 'rails_helper'
|
2013-07-03 20:47:12 -05:00
|
|
|
|
2017-05-11 17:23:18 -05:00
|
|
|
RSpec.describe TopicTimer, type: :model do
|
2020-04-20 23:38:35 -05:00
|
|
|
fab!(:topic_timer) { Fabricate(:topic_timer) }
|
2019-05-06 22:12:20 -05:00
|
|
|
fab!(:topic) { Fabricate(:topic) }
|
|
|
|
fab!(:admin) { Fabricate(:admin) }
|
2015-12-08 06:43:23 -06:00
|
|
|
|
2020-04-20 23:38:35 -05:00
|
|
|
before { freeze_time }
|
2018-06-05 02:29:17 -05:00
|
|
|
|
2017-03-21 22:12:02 -05:00
|
|
|
context "validations" do
|
|
|
|
describe '#status_type' do
|
2017-05-16 13:49:42 -05:00
|
|
|
it 'should ensure that only one active public topic status update exists' do
|
2017-05-11 17:23:18 -05:00
|
|
|
topic_timer.update!(topic: topic)
|
|
|
|
Fabricate(:topic_timer, deleted_at: Time.zone.now, topic: topic)
|
2014-10-29 15:26:32 -05:00
|
|
|
|
2017-05-11 17:23:18 -05:00
|
|
|
expect { Fabricate(:topic_timer, topic: topic) }
|
2017-03-21 22:12:02 -05:00
|
|
|
.to raise_error(ActiveRecord::RecordInvalid)
|
|
|
|
end
|
2017-05-16 13:49:42 -05:00
|
|
|
|
|
|
|
it 'should ensure that only one active private topic timer exists per user' do
|
|
|
|
Fabricate(:topic_timer, topic: topic, user: admin, status_type: TopicTimer.types[:reminder])
|
|
|
|
|
|
|
|
expect { Fabricate(:topic_timer, topic: topic, user: admin, status_type: TopicTimer.types[:reminder]) }
|
|
|
|
.to raise_error(ActiveRecord::RecordInvalid)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should allow users to have their own private topic timer' do
|
2017-05-16 20:37:11 -05:00
|
|
|
expect do
|
|
|
|
Fabricate(:topic_timer,
|
|
|
|
topic: topic,
|
|
|
|
user: Fabricate(:admin),
|
|
|
|
status_type: TopicTimer.types[:reminder]
|
|
|
|
)
|
|
|
|
end.to_not raise_error
|
2017-05-16 13:49:42 -05:00
|
|
|
end
|
2017-03-21 22:12:02 -05:00
|
|
|
end
|
2014-10-29 15:26:32 -05:00
|
|
|
|
2017-03-21 22:12:02 -05:00
|
|
|
describe '#execute_at' do
|
|
|
|
describe 'when #execute_at is greater than #created_at' do
|
|
|
|
it 'should be valid' do
|
2017-05-11 17:23:18 -05:00
|
|
|
topic_timer = Fabricate.build(:topic_timer,
|
2017-03-21 22:12:02 -05:00
|
|
|
execute_at: Time.zone.now + 1.hour,
|
|
|
|
user: Fabricate(:user),
|
|
|
|
topic: Fabricate(:topic)
|
|
|
|
)
|
2013-07-03 20:47:12 -05:00
|
|
|
|
2017-05-11 17:23:18 -05:00
|
|
|
expect(topic_timer).to be_valid
|
2017-03-21 22:12:02 -05:00
|
|
|
end
|
|
|
|
end
|
2013-07-03 20:47:12 -05:00
|
|
|
|
2017-03-21 22:12:02 -05:00
|
|
|
describe 'when #execute_at is smaller than #created_at' do
|
|
|
|
it 'should not be valid' do
|
2017-05-11 17:23:18 -05:00
|
|
|
topic_timer = Fabricate.build(:topic_timer,
|
2017-03-21 22:12:02 -05:00
|
|
|
execute_at: Time.zone.now - 1.hour,
|
|
|
|
created_at: Time.zone.now,
|
|
|
|
user: Fabricate(:user),
|
|
|
|
topic: Fabricate(:topic)
|
|
|
|
)
|
2013-07-03 20:47:12 -05:00
|
|
|
|
2017-05-11 17:23:18 -05:00
|
|
|
expect(topic_timer).to_not be_valid
|
2017-03-21 22:12:02 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-04-07 02:26:15 -05:00
|
|
|
|
|
|
|
describe '#category_id' do
|
|
|
|
describe 'when #status_type is publish_to_category' do
|
|
|
|
describe 'when #category_id is not present' do
|
|
|
|
it 'should not be valid' do
|
2017-05-11 17:23:18 -05:00
|
|
|
topic_timer = Fabricate.build(:topic_timer,
|
|
|
|
status_type: TopicTimer.types[:publish_to_category]
|
2017-04-07 02:26:15 -05:00
|
|
|
)
|
|
|
|
|
2017-05-11 17:23:18 -05:00
|
|
|
expect(topic_timer).to_not be_valid
|
2019-04-30 01:58:18 -05:00
|
|
|
expect(topic_timer.errors).to include(:category_id)
|
2017-04-07 02:26:15 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'when #category_id is present' do
|
|
|
|
it 'should be valid' do
|
2017-05-11 17:23:18 -05:00
|
|
|
topic_timer = Fabricate.build(:topic_timer,
|
|
|
|
status_type: TopicTimer.types[:publish_to_category],
|
2017-04-07 02:26:15 -05:00
|
|
|
category_id: Fabricate(:category).id,
|
|
|
|
user: Fabricate(:user),
|
|
|
|
topic: Fabricate(:topic)
|
|
|
|
)
|
|
|
|
|
2017-05-11 17:23:18 -05:00
|
|
|
expect(topic_timer).to be_valid
|
2017-04-07 02:26:15 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-07-03 20:47:12 -05:00
|
|
|
end
|
2014-10-29 15:26:32 -05:00
|
|
|
|
2017-03-21 22:12:02 -05:00
|
|
|
context 'callbacks' do
|
|
|
|
describe 'when #execute_at and #user_id are not changed' do
|
|
|
|
it 'should not schedule another to update topic' do
|
2020-04-20 23:38:35 -05:00
|
|
|
Jobs.expects(:enqueue_at).never
|
2017-03-21 22:12:02 -05:00
|
|
|
Jobs.expects(:cancel_scheduled_job).never
|
|
|
|
|
2017-05-11 17:23:18 -05:00
|
|
|
topic_timer.update!(topic: Fabricate(:topic))
|
2017-03-21 22:12:02 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'when #execute_at value is changed' do
|
|
|
|
it 'reschedules the job' do
|
2017-07-24 08:17:42 -05:00
|
|
|
Jobs.expects(:cancel_scheduled_job).with(
|
|
|
|
:toggle_topic_closed, topic_timer_id: topic_timer.id
|
|
|
|
)
|
2017-03-21 22:12:02 -05:00
|
|
|
|
2020-07-24 04:16:52 -05:00
|
|
|
expect_enqueued_with(job: :toggle_topic_closed, args: { topic_timer_id: topic_timer.id, state: true }, at: 3.days.from_now) do
|
|
|
|
topic_timer.update!(execute_at: 3.days.from_now, created_at: Time.zone.now)
|
|
|
|
end
|
2017-03-21 22:12:02 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
describe 'when execute_at is smaller than the current time' do
|
|
|
|
it 'should enqueue the job immediately' do
|
2020-07-24 04:16:52 -05:00
|
|
|
expect_enqueued_with(job: :toggle_topic_closed, args: { topic_timer_id: topic_timer.id, state: true }, at: Time.zone.now) do
|
|
|
|
topic_timer.update!(
|
|
|
|
execute_at: Time.zone.now - 1.hour,
|
|
|
|
created_at: Time.zone.now - 2.hour
|
|
|
|
)
|
|
|
|
end
|
2017-03-21 22:12:02 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'when user is changed' do
|
|
|
|
it 'should update the job' do
|
2017-07-24 08:17:42 -05:00
|
|
|
Jobs.expects(:cancel_scheduled_job).with(
|
|
|
|
:toggle_topic_closed, topic_timer_id: topic_timer.id
|
|
|
|
)
|
2017-03-21 22:12:02 -05:00
|
|
|
|
2020-07-24 04:16:52 -05:00
|
|
|
expect_enqueued_with(job: :toggle_topic_closed, args: { topic_timer_id: topic_timer.id, state: true }, at: topic_timer.execute_at) do
|
|
|
|
topic_timer.update!(user: admin)
|
|
|
|
end
|
2017-03-21 22:12:02 -05:00
|
|
|
end
|
|
|
|
end
|
2017-04-02 20:06:15 -05:00
|
|
|
|
2020-08-25 20:32:11 -05:00
|
|
|
describe 'when a open topic status update is created for an open topic' do
|
2019-05-06 22:12:20 -05:00
|
|
|
fab!(:topic) { Fabricate(:topic, closed: false) }
|
2020-04-20 23:38:35 -05:00
|
|
|
fab!(:topic_timer) do
|
2017-05-11 17:23:18 -05:00
|
|
|
Fabricate(:topic_timer,
|
2017-04-02 20:06:15 -05:00
|
|
|
status_type: described_class.types[:open],
|
|
|
|
topic: topic
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2018-05-31 02:53:49 -05:00
|
|
|
before do
|
2019-03-14 09:47:38 -05:00
|
|
|
Jobs.run_immediately!
|
2018-05-31 02:53:49 -05:00
|
|
|
end
|
|
|
|
|
2020-08-25 20:32:11 -05:00
|
|
|
it 'should close the topic' do
|
2017-05-11 17:23:18 -05:00
|
|
|
topic_timer
|
2020-08-25 20:32:11 -05:00
|
|
|
expect(topic.reload.closed).to eq(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'when topic has been deleted' do
|
|
|
|
it 'should not queue the job' do
|
|
|
|
topic.trash!
|
|
|
|
topic_timer
|
|
|
|
|
|
|
|
expect(Jobs::ToggleTopicClosed.jobs).to eq([])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-04-02 20:06:15 -05:00
|
|
|
|
2020-08-25 20:32:11 -05:00
|
|
|
describe 'when a close topic status update is created for a closed topic' do
|
|
|
|
fab!(:topic) { Fabricate(:topic, closed: true) }
|
|
|
|
fab!(:topic_timer) do
|
|
|
|
Fabricate(:topic_timer,
|
|
|
|
status_type: described_class.types[:close],
|
|
|
|
topic: topic
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
Jobs.run_immediately!
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should open the topic' do
|
|
|
|
topic_timer
|
|
|
|
expect(topic.reload.closed).to eq(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'when topic has been deleted' do
|
|
|
|
it 'should not queue the job' do
|
|
|
|
topic.trash!
|
|
|
|
topic_timer
|
|
|
|
|
|
|
|
expect(Jobs::ToggleTopicClosed.jobs).to eq([])
|
|
|
|
end
|
2017-04-02 20:06:15 -05:00
|
|
|
end
|
|
|
|
end
|
2017-05-16 13:49:42 -05:00
|
|
|
|
2017-05-16 20:37:11 -05:00
|
|
|
describe '#public_type' do
|
2017-05-16 13:49:42 -05:00
|
|
|
[:close, :open, :delete].each do |public_type|
|
|
|
|
it "is true for #{public_type}" do
|
|
|
|
timer = Fabricate(:topic_timer, status_type: described_class.types[public_type])
|
|
|
|
expect(timer.public_type).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is true for publish_to_category" do
|
|
|
|
timer = Fabricate(:topic_timer, status_type: described_class.types[:publish_to_category], category: Fabricate(:category))
|
|
|
|
expect(timer.public_type).to eq(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.private_types.keys.each do |private_type|
|
|
|
|
it "is false for #{private_type}" do
|
|
|
|
timer = Fabricate(:topic_timer, status_type: described_class.types[private_type])
|
|
|
|
expect(timer.public_type).to be_falsey
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2014-10-29 15:26:32 -05:00
|
|
|
end
|
|
|
|
|
2017-03-21 22:12:02 -05:00
|
|
|
describe '.ensure_consistency!' do
|
|
|
|
it 'should enqueue jobs that have been missed' do
|
2017-05-11 17:23:18 -05:00
|
|
|
close_topic_timer = Fabricate(:topic_timer,
|
2017-03-21 22:12:02 -05:00
|
|
|
execute_at: Time.zone.now - 1.hour,
|
|
|
|
created_at: Time.zone.now - 2.hour
|
|
|
|
)
|
2014-10-29 15:26:32 -05:00
|
|
|
|
2017-05-11 17:23:18 -05:00
|
|
|
open_topic_timer = Fabricate(:topic_timer,
|
2017-03-21 22:12:02 -05:00
|
|
|
status_type: described_class.types[:open],
|
|
|
|
execute_at: Time.zone.now - 1.hour,
|
2017-06-21 01:31:15 -05:00
|
|
|
created_at: Time.zone.now - 2.hour,
|
|
|
|
topic: Fabricate(:topic, closed: true)
|
2017-03-21 22:12:02 -05:00
|
|
|
)
|
|
|
|
|
2018-08-14 05:35:20 -05:00
|
|
|
Fabricate(:topic_timer, execute_at: Time.zone.now + 1.hour)
|
2017-03-21 22:12:02 -05:00
|
|
|
|
2020-08-26 03:10:13 -05:00
|
|
|
trashed_topic_timer = Fabricate(:topic_timer,
|
2017-04-12 23:02:35 -05:00
|
|
|
execute_at: Time.zone.now - 1.hour,
|
|
|
|
created_at: Time.zone.now - 2.hour
|
2020-08-26 03:10:13 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
trashed_topic_timer.topic.trash!
|
2017-04-12 23:02:35 -05:00
|
|
|
|
2018-08-14 05:35:20 -05:00
|
|
|
# creating topic timers already enqueues jobs
|
|
|
|
# let's delete them to test ensure_consistency!
|
|
|
|
Sidekiq::Worker.clear_all
|
|
|
|
|
2017-03-21 22:12:02 -05:00
|
|
|
expect { described_class.ensure_consistency! }
|
2020-08-26 03:10:13 -05:00
|
|
|
.to change { Jobs::ToggleTopicClosed.jobs.count }.by(3)
|
|
|
|
|
|
|
|
expect(job_enqueued?(job: :toggle_topic_closed, args: {
|
|
|
|
topic_timer_id: close_topic_timer.id,
|
|
|
|
state: true
|
|
|
|
})).to eq(true)
|
|
|
|
|
|
|
|
expect(job_enqueued?(job: :toggle_topic_closed, args: {
|
|
|
|
topic_timer_id: open_topic_timer.id,
|
|
|
|
state: false
|
|
|
|
})).to eq(true)
|
|
|
|
|
|
|
|
expect(job_enqueued?(job: :toggle_topic_closed, args: {
|
|
|
|
topic_timer_id: trashed_topic_timer.id,
|
|
|
|
state: true
|
|
|
|
})).to eq(true)
|
2017-03-21 22:12:02 -05:00
|
|
|
end
|
2017-05-16 13:49:42 -05:00
|
|
|
|
2018-08-14 05:35:20 -05:00
|
|
|
it "should enqueue remind me jobs that have been missed" do
|
|
|
|
reminder = Fabricate(:topic_timer,
|
|
|
|
status_type: described_class.types[:reminder],
|
|
|
|
execute_at: Time.zone.now - 1.hour,
|
|
|
|
created_at: Time.zone.now - 2.hour
|
|
|
|
)
|
2017-05-17 11:46:41 -05:00
|
|
|
|
2018-08-14 05:35:20 -05:00
|
|
|
# creating topic timers already enqueues jobs
|
|
|
|
# let's delete them to test ensure_consistency!
|
|
|
|
Sidekiq::Worker.clear_all
|
2017-05-17 11:46:41 -05:00
|
|
|
|
2018-08-14 05:35:20 -05:00
|
|
|
expect { described_class.ensure_consistency! }
|
|
|
|
.to change { Jobs::TopicReminder.jobs.count }.by(1)
|
|
|
|
|
|
|
|
job_args = Jobs::TopicReminder.jobs.first["args"].first
|
|
|
|
expect(job_args["topic_timer_id"]).to eq(reminder.id)
|
|
|
|
end
|
2014-10-29 15:26:32 -05:00
|
|
|
end
|
2013-07-03 20:47:12 -05:00
|
|
|
end
|