DEV: Update the rubocop-discourse gem

This enables cops related to RSpec `subject`.

See https://github.com/discourse/rubocop-discourse/pull/32
This commit is contained in:
Loïc Guitaut 2023-06-21 16:00:19 +02:00 committed by Loïc Guitaut
parent 8e1d049e6b
commit 0f4beab0fb
129 changed files with 1697 additions and 1506 deletions

View File

@ -191,6 +191,7 @@ GEM
simpleidn (~> 0.2) simpleidn (~> 0.2)
jwt (2.7.1) jwt (2.7.1)
kgio (2.11.4) kgio (2.11.4)
language_server-protocol (3.17.0.3)
libv8-node (18.16.0.0) libv8-node (18.16.0.0)
libv8-node (18.16.0.0-aarch64-linux) libv8-node (18.16.0.0-aarch64-linux)
libv8-node (18.16.0.0-arm64-darwin) libv8-node (18.16.0.0-arm64-darwin)
@ -409,8 +410,9 @@ GEM
rspec-core (>= 2.14) rspec-core (>= 2.14)
rtlcss (0.2.1) rtlcss (0.2.1)
mini_racer (>= 0.6.3) mini_racer (>= 0.6.3)
rubocop (1.52.1) rubocop (1.53.0)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.2.2.3) parser (>= 3.2.2.3)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
@ -423,7 +425,7 @@ GEM
parser (>= 3.2.1.0) parser (>= 3.2.1.0)
rubocop-capybara (2.18.0) rubocop-capybara (2.18.0)
rubocop (~> 1.41) rubocop (~> 1.41)
rubocop-discourse (3.2.0) rubocop-discourse (3.3.0)
rubocop (>= 1.1.0) rubocop (>= 1.1.0)
rubocop-rspec (>= 2.0.0) rubocop-rspec (>= 2.0.0)
rubocop-factory_bot (2.23.1) rubocop-factory_bot (2.23.1)

View File

@ -3,13 +3,15 @@
require "rails_helper" require "rails_helper"
describe Jobs::Chat::AutoJoinChannelBatch do describe Jobs::Chat::AutoJoinChannelBatch do
subject(:job) { described_class.new }
describe "#execute" do describe "#execute" do
fab!(:category) { Fabricate(:category) } fab!(:category) { Fabricate(:category) }
let!(:user) { Fabricate(:user, last_seen_at: 15.minutes.ago) } let!(:user) { Fabricate(:user, last_seen_at: 15.minutes.ago) }
let(:channel) { Fabricate(:chat_channel, auto_join_users: true, chatable: category) } let(:channel) { Fabricate(:chat_channel, auto_join_users: true, chatable: category) }
it "joins all valid users in the batch" do it "joins all valid users in the batch" do
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
assert_users_follows_channel(channel, [user]) assert_users_follows_channel(channel, [user])
end end
@ -17,7 +19,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "doesn't join users outside the batch" do it "doesn't join users outside the batch" do
another_user = Fabricate(:user, last_seen_at: 15.minutes.ago) another_user = Fabricate(:user, last_seen_at: 15.minutes.ago)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
assert_users_follows_channel(channel, [user]) assert_users_follows_channel(channel, [user])
assert_user_skipped(channel, another_user) assert_user_skipped(channel, another_user)
@ -26,7 +28,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "doesn't join suspended users" do it "doesn't join suspended users" do
user.update!(suspended_till: 1.year.from_now) user.update!(suspended_till: 1.year.from_now)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
assert_user_skipped(channel, user) assert_user_skipped(channel, user)
end end
@ -34,7 +36,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "doesn't join users last_seen more than 3 months ago" do it "doesn't join users last_seen more than 3 months ago" do
user.update!(last_seen_at: 4.months.ago) user.update!(last_seen_at: 4.months.ago)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
assert_user_skipped(channel, user) assert_user_skipped(channel, user)
end end
@ -42,13 +44,13 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "joins users with last_seen set to null" do it "joins users with last_seen set to null" do
user.update!(last_seen_at: nil) user.update!(last_seen_at: nil)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
assert_users_follows_channel(channel, [user]) assert_users_follows_channel(channel, [user])
end end
it "does nothing if the channel is invalid" do it "does nothing if the channel is invalid" do
subject.execute(chat_channel_id: -1, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: -1, starts_at: user.id, ends_at: user.id)
assert_user_skipped(channel, user) assert_user_skipped(channel, user)
end end
@ -57,13 +59,13 @@ describe Jobs::Chat::AutoJoinChannelBatch do
direct_message = Fabricate(:direct_message) direct_message = Fabricate(:direct_message)
channel.update!(chatable: direct_message) channel.update!(chatable: direct_message)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
assert_user_skipped(channel, user) assert_user_skipped(channel, user)
end end
it "enqueues the user count update job and marks the channel user count as stale" do it "enqueues the user count update job and marks the channel user count as stale" do
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
expect_job_enqueued( expect_job_enqueued(
job: Jobs::Chat::UpdateChannelUserCount, job: Jobs::Chat::UpdateChannelUserCount,
args: { args: {
@ -81,7 +83,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
args: { args: {
chat_channel_id: channel.id, chat_channel_id: channel.id,
}, },
) { subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id) } ) { job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id) }
expect(channel.reload.user_count_stale).to eq(false) expect(channel.reload.user_count_stale).to eq(false)
end end
@ -89,13 +91,13 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "ignores users without chat_enabled" do it "ignores users without chat_enabled" do
user.user_option.update!(chat_enabled: false) user.user_option.update!(chat_enabled: false)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
assert_user_skipped(channel, user) assert_user_skipped(channel, user)
end end
it "sets the join reason to automatic" do it "sets the join reason to automatic" do
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
new_membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel) new_membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel)
expect(new_membership.automatic?).to eq(true) expect(new_membership.automatic?).to eq(true)
@ -104,7 +106,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "skips anonymous users" do it "skips anonymous users" do
user_2 = Fabricate(:anonymous) user_2 = Fabricate(:anonymous)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id)
assert_users_follows_channel(channel, [user]) assert_users_follows_channel(channel, [user])
assert_user_skipped(channel, user_2) assert_user_skipped(channel, user_2)
@ -113,7 +115,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "skips non-active users" do it "skips non-active users" do
user_2 = Fabricate(:user, active: false, last_seen_at: 15.minutes.ago) user_2 = Fabricate(:user, active: false, last_seen_at: 15.minutes.ago)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id)
assert_users_follows_channel(channel, [user]) assert_users_follows_channel(channel, [user])
assert_user_skipped(channel, user_2) assert_user_skipped(channel, user_2)
@ -122,7 +124,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "skips staged users" do it "skips staged users" do
user_2 = Fabricate(:user, staged: true, last_seen_at: 15.minutes.ago) user_2 = Fabricate(:user, staged: true, last_seen_at: 15.minutes.ago)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id)
assert_users_follows_channel(channel, [user]) assert_users_follows_channel(channel, [user])
assert_user_skipped(channel, user_2) assert_user_skipped(channel, user_2)
@ -131,7 +133,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "adds every user in the batch" do it "adds every user in the batch" do
user_2 = Fabricate(:user, last_seen_at: 15.minutes.ago) user_2 = Fabricate(:user, last_seen_at: 15.minutes.ago)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user_2.id)
assert_users_follows_channel(channel, [user, user_2]) assert_users_follows_channel(channel, [user, user_2])
end end
@ -139,7 +141,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "publishes a message only to joined users" do it "publishes a message only to joined users" do
messages = messages =
MessageBus.track_publish("/chat/new-channel") do MessageBus.track_publish("/chat/new-channel") do
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
end end
expect(messages.size).to eq(1) expect(messages.size).to eq(1)
@ -156,7 +158,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
it "only joins group members with access to the category" do it "only joins group members with access to the category" do
another_user = Fabricate(:user, last_seen_at: 15.minutes.ago) another_user = Fabricate(:user, last_seen_at: 15.minutes.ago)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: another_user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: another_user.id)
assert_users_follows_channel(channel, [user]) assert_users_follows_channel(channel, [user])
assert_user_skipped(channel, another_user) assert_user_skipped(channel, another_user)
@ -167,7 +169,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
Fabricate(:category_group, category: category, group: second_chatters_group) Fabricate(:category_group, category: category, group: second_chatters_group)
second_chatters_group.add(user) second_chatters_group.add(user)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: user.id)
assert_users_follows_channel(channel, [user]) assert_users_follows_channel(channel, [user])
end end
@ -176,7 +178,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
another_user = Fabricate(:user, last_seen_at: 15.minutes.ago) another_user = Fabricate(:user, last_seen_at: 15.minutes.ago)
chatters_group.add(another_user) chatters_group.add(another_user)
subject.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: another_user.id) job.execute(chat_channel_id: channel.id, starts_at: user.id, ends_at: another_user.id)
assert_users_follows_channel(channel, [user, another_user]) assert_users_follows_channel(channel, [user, another_user])
end end
@ -195,7 +197,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
) )
non_chatters_group.add(another_user) non_chatters_group.add(another_user)
subject.execute( job.execute(
chat_channel_id: readonly_channel.id, chat_channel_id: readonly_channel.id,
starts_at: another_user.id, starts_at: another_user.id,
ends_at: another_user.id, ends_at: another_user.id,
@ -227,7 +229,7 @@ describe Jobs::Chat::AutoJoinChannelBatch do
) )
other_group.add(another_user) other_group.add(another_user)
subject.execute( job.execute(
chat_channel_id: private_channel.id, chat_channel_id: private_channel.id,
starts_at: another_user.id, starts_at: another_user.id,
ends_at: another_user.id, ends_at: another_user.id,

View File

@ -2,12 +2,14 @@
RSpec.describe Jobs::Chat::DeleteUserMessages do RSpec.describe Jobs::Chat::DeleteUserMessages do
describe "#execute" do describe "#execute" do
subject(:execute) { described_class.new.execute(user_id: user_1) }
fab!(:user_1) { Fabricate(:user) } fab!(:user_1) { Fabricate(:user) }
fab!(:channel) { Fabricate(:chat_channel) } fab!(:channel) { Fabricate(:chat_channel) }
fab!(:chat_message) { Fabricate(:chat_message, chat_channel: channel, user: user_1) } fab!(:chat_message) { Fabricate(:chat_message, chat_channel: channel, user: user_1) }
it "deletes messages from the user" do it "deletes messages from the user" do
subject.execute(user_id: user_1) execute
expect { chat_message.reload }.to raise_error(ActiveRecord::RecordNotFound) expect { chat_message.reload }.to raise_error(ActiveRecord::RecordNotFound)
end end
@ -16,7 +18,7 @@ RSpec.describe Jobs::Chat::DeleteUserMessages do
user_2 = Fabricate(:user) user_2 = Fabricate(:user)
user_2_message = Fabricate(:chat_message, chat_channel: channel, user: user_2) user_2_message = Fabricate(:chat_message, chat_channel: channel, user: user_2)
subject.execute(user_id: user_1) execute
expect(user_2_message.reload).to be_present expect(user_2_message.reload).to be_present
end end
@ -24,7 +26,7 @@ RSpec.describe Jobs::Chat::DeleteUserMessages do
it "deletes trashed messages" do it "deletes trashed messages" do
chat_message.trash! chat_message.trash!
subject.execute(user_id: user_1) execute
expect(Chat::Message.with_deleted.where(id: chat_message.id)).to be_empty expect(Chat::Message.with_deleted.where(id: chat_message.id)).to be_empty
end end

View File

@ -3,6 +3,8 @@
require "rails_helper" require "rails_helper"
describe Jobs::Chat::NotifyMentioned do describe Jobs::Chat::NotifyMentioned do
subject(:job) { described_class.new }
fab!(:user_1) { Fabricate(:user) } fab!(:user_1) { Fabricate(:user) }
fab!(:user_2) { Fabricate(:user) } fab!(:user_2) { Fabricate(:user) }
fab!(:public_channel) { Fabricate(:category_channel) } fab!(:public_channel) { Fabricate(:category_channel) }
@ -47,7 +49,7 @@ describe Jobs::Chat::NotifyMentioned do
) )
MessageBus MessageBus
.track_publish("/chat/notification-alert/#{user.id}") do .track_publish("/chat/notification-alert/#{user.id}") do
subject.execute( job.execute(
chat_message_id: message.id, chat_message_id: message.id,
timestamp: message.created_at, timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map, to_notify_ids_map: to_notify_ids_map,
@ -58,7 +60,7 @@ describe Jobs::Chat::NotifyMentioned do
end end
def track_core_notification(user: user_2, message:, to_notify_ids_map:) def track_core_notification(user: user_2, message:, to_notify_ids_map:)
subject.execute( job.execute(
chat_message_id: message.id, chat_message_id: message.id,
timestamp: message.created_at, timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map, to_notify_ids_map: to_notify_ids_map,
@ -175,7 +177,7 @@ describe Jobs::Chat::NotifyMentioned do
PostAlerter.expects(:push_notification).never PostAlerter.expects(:push_notification).never
subject.execute( job.execute(
chat_message_id: message.id, chat_message_id: message.id,
timestamp: message.created_at, timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map, to_notify_ids_map: to_notify_ids_map,
@ -204,7 +206,7 @@ describe Jobs::Chat::NotifyMentioned do
PostAlerter.expects(:push_notification).never PostAlerter.expects(:push_notification).never
subject.execute( job.execute(
chat_message_id: message.id, chat_message_id: message.id,
timestamp: message.created_at, timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map, to_notify_ids_map: to_notify_ids_map,
@ -248,7 +250,7 @@ describe Jobs::Chat::NotifyMentioned do
}, },
) )
subject.execute( job.execute(
chat_message_id: message.id, chat_message_id: message.id,
timestamp: message.created_at, timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map, to_notify_ids_map: to_notify_ids_map,

View File

@ -1,13 +1,15 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::Chat::SendMessageNotifications do RSpec.describe Jobs::Chat::SendMessageNotifications do
subject(:job) { described_class.new }
describe "#execute" do describe "#execute" do
context "when the message doesn't exist" do context "when the message doesn't exist" do
it "does nothing" do it "does nothing" do
Chat::Notifier.any_instance.expects(:notify_new).never Chat::Notifier.any_instance.expects(:notify_new).never
Chat::Notifier.any_instance.expects(:notify_edit).never Chat::Notifier.any_instance.expects(:notify_edit).never
subject.execute(eason: "new", timestamp: 1.minute.ago) job.execute(reason: "new", timestamp: 1.minute.ago)
end end
end end
@ -18,32 +20,28 @@ RSpec.describe Jobs::Chat::SendMessageNotifications do
Chat::Notifier.expects(:notify_new).never Chat::Notifier.expects(:notify_new).never
Chat::Notifier.expects(:notify_edit).never Chat::Notifier.expects(:notify_edit).never
subject.execute( job.execute(chat_message_id: chat_message.id, reason: "invalid", timestamp: 1.minute.ago)
chat_message_id: chat_message.id,
reason: "invalid",
timestamp: 1.minute.ago,
)
end end
it "does nothing if there is no timestamp" do it "does nothing if there is no timestamp" do
Chat::Notifier.any_instance.expects(:notify_new).never Chat::Notifier.any_instance.expects(:notify_new).never
Chat::Notifier.any_instance.expects(:notify_edit).never Chat::Notifier.any_instance.expects(:notify_edit).never
subject.execute(chat_message_id: chat_message.id, reason: "new") job.execute(chat_message_id: chat_message.id, reason: "new")
end end
it "calls notify_new when the reason is 'new'" do it "calls notify_new when the reason is 'new'" do
Chat::Notifier.any_instance.expects(:notify_new).once Chat::Notifier.any_instance.expects(:notify_new).once
Chat::Notifier.any_instance.expects(:notify_edit).never Chat::Notifier.any_instance.expects(:notify_edit).never
subject.execute(chat_message_id: chat_message.id, reason: "new", timestamp: 1.minute.ago) job.execute(chat_message_id: chat_message.id, reason: "new", timestamp: 1.minute.ago)
end end
it "calls notify_edit when the reason is 'edit'" do it "calls notify_edit when the reason is 'edit'" do
Chat::Notifier.any_instance.expects(:notify_new).never Chat::Notifier.any_instance.expects(:notify_new).never
Chat::Notifier.any_instance.expects(:notify_edit).once Chat::Notifier.any_instance.expects(:notify_edit).once
subject.execute(chat_message_id: chat_message.id, reason: "edit", timestamp: 1.minute.ago) job.execute(chat_message_id: chat_message.id, reason: "edit", timestamp: 1.minute.ago)
end end
end end
end end

View File

@ -3,6 +3,8 @@
require "rails_helper" require "rails_helper"
describe Jobs::Chat::AutoJoinUsers do describe Jobs::Chat::AutoJoinUsers do
subject(:job) { described_class.new }
it "works" do it "works" do
Jobs.run_immediately! Jobs.run_immediately!
channel = Fabricate(:category_channel, auto_join_users: true) channel = Fabricate(:category_channel, auto_join_users: true)
@ -11,7 +13,7 @@ describe Jobs::Chat::AutoJoinUsers do
membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel) membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel)
expect(membership).to be_nil expect(membership).to be_nil
subject.execute({}) job.execute({})
membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel) membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel)
expect(membership.following).to eq(true) expect(membership.following).to eq(true)

View File

@ -9,8 +9,8 @@ describe Chat::ChannelArchiveService do
fab!(:channel) { Fabricate(:category_channel) } fab!(:channel) { Fabricate(:category_channel) }
fab!(:user) { Fabricate(:user, admin: true) } fab!(:user) { Fabricate(:user, admin: true) }
fab!(:category) { Fabricate(:category) } fab!(:category) { Fabricate(:category) }
let(:topic_params) { { topic_title: "This will be a new topic", category_id: category.id } } let(:topic_params) { { topic_title: "This will be a new topic", category_id: category.id } }
subject { Chat::ChannelArchiveService }
before { SiteSetting.chat_enabled = true } before { SiteSetting.chat_enabled = true }
@ -18,7 +18,7 @@ describe Chat::ChannelArchiveService do
before { 3.times { Fabricate(:chat_message, chat_channel: channel) } } before { 3.times { Fabricate(:chat_message, chat_channel: channel) } }
it "marks the channel as read_only" do it "marks the channel as read_only" do
subject.create_archive_process( described_class.create_archive_process(
chat_channel: channel, chat_channel: channel,
acting_user: user, acting_user: user,
topic_params: topic_params, topic_params: topic_params,
@ -27,7 +27,7 @@ describe Chat::ChannelArchiveService do
end end
it "creates the chat channel archive record to save progress and topic params" do it "creates the chat channel archive record to save progress and topic params" do
subject.create_archive_process( described_class.create_archive_process(
chat_channel: channel, chat_channel: channel,
acting_user: user, acting_user: user,
topic_params: topic_params, topic_params: topic_params,
@ -42,7 +42,7 @@ describe Chat::ChannelArchiveService do
it "enqueues the archive job" do it "enqueues the archive job" do
channel_archive = channel_archive =
subject.create_archive_process( described_class.create_archive_process(
chat_channel: channel, chat_channel: channel,
acting_user: user, acting_user: user,
topic_params: topic_params, topic_params: topic_params,
@ -58,13 +58,13 @@ describe Chat::ChannelArchiveService do
end end
it "does nothing if there is already an archive record for the channel" do it "does nothing if there is already an archive record for the channel" do
subject.create_archive_process( described_class.create_archive_process(
chat_channel: channel, chat_channel: channel,
acting_user: user, acting_user: user,
topic_params: topic_params, topic_params: topic_params,
) )
expect { expect {
subject.create_archive_process( described_class.create_archive_process(
chat_channel: channel, chat_channel: channel,
acting_user: user, acting_user: user,
topic_params: topic_params, topic_params: topic_params,
@ -76,7 +76,7 @@ describe Chat::ChannelArchiveService do
new_message = Fabricate(:chat_message, chat_channel: channel) new_message = Fabricate(:chat_message, chat_channel: channel)
new_message.trash! new_message.trash!
channel_archive = channel_archive =
subject.create_archive_process( described_class.create_archive_process(
chat_channel: channel, chat_channel: channel,
acting_user: user, acting_user: user,
topic_params: topic_params, topic_params: topic_params,
@ -92,7 +92,7 @@ describe Chat::ChannelArchiveService do
def start_archive def start_archive
@channel_archive = @channel_archive =
subject.create_archive_process( described_class.create_archive_process(
chat_channel: channel, chat_channel: channel,
acting_user: user, acting_user: user,
topic_params: topic_params, topic_params: topic_params,
@ -113,7 +113,7 @@ describe Chat::ChannelArchiveService do
emoji: "+1", emoji: "+1",
) )
stub_const(Chat::ChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do stub_const(Chat::ChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
end end
@channel_archive.reload @channel_archive.reload
@ -146,21 +146,21 @@ describe Chat::ChannelArchiveService do
it "does not stop the process if the post length is too high (validations disabled)" do it "does not stop the process if the post length is too high (validations disabled)" do
create_messages(50) && start_archive create_messages(50) && start_archive
SiteSetting.max_post_length = 1 SiteSetting.max_post_length = 1
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
expect(@channel_archive.reload.complete?).to eq(true) expect(@channel_archive.reload.complete?).to eq(true)
end end
it "successfully links uploads from messages to the post" do it "successfully links uploads from messages to the post" do
create_messages(3) && start_archive create_messages(3) && start_archive
UploadReference.create!(target: Chat::Message.last, upload: Fabricate(:upload)) UploadReference.create!(target: Chat::Message.last, upload: Fabricate(:upload))
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
expect(@channel_archive.reload.complete?).to eq(true) expect(@channel_archive.reload.complete?).to eq(true)
expect(@channel_archive.destination_topic.posts.last.upload_references.count).to eq(1) expect(@channel_archive.destination_topic.posts.last.upload_references.count).to eq(1)
end end
it "successfully sends a private message to the archiving user" do it "successfully sends a private message to the archiving user" do
create_messages(3) && start_archive create_messages(3) && start_archive
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
expect(@channel_archive.reload.complete?).to eq(true) expect(@channel_archive.reload.complete?).to eq(true)
pm_topic = Topic.private_messages.last pm_topic = Topic.private_messages.last
expect(pm_topic.topic_allowed_users.first.user).to eq(@channel_archive.archived_by) expect(pm_topic.topic_allowed_users.first.user).to eq(@channel_archive.archived_by)
@ -174,7 +174,7 @@ describe Chat::ChannelArchiveService do
create_messages(3) && start_archive create_messages(3) && start_archive
@channel_archive.update!(destination_topic_title: "Wow this is the new title :tada: :joy:") @channel_archive.update!(destination_topic_title: "Wow this is the new title :tada: :joy:")
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
expect(@channel_archive.reload.complete?).to eq(false) expect(@channel_archive.reload.complete?).to eq(false)
expect(@channel_archive.reload.failed?).to eq(true) expect(@channel_archive.reload.failed?).to eq(true)
expect(@channel_archive.archive_error).to eq("Title can't have more than 1 emoji") expect(@channel_archive.archive_error).to eq("Title can't have more than 1 emoji")
@ -191,7 +191,7 @@ describe Chat::ChannelArchiveService do
it "uses the channel slug to autolink a hashtag for the channel in the PM" do it "uses the channel slug to autolink a hashtag for the channel in the PM" do
create_messages(3) && start_archive create_messages(3) && start_archive
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
expect(@channel_archive.reload.complete?).to eq(true) expect(@channel_archive.reload.complete?).to eq(true)
pm_topic = Topic.private_messages.last pm_topic = Topic.private_messages.last
expect(pm_topic.first_post.cooked).to have_tag( expect(pm_topic.first_post.cooked).to have_tag(
@ -231,7 +231,7 @@ describe Chat::ChannelArchiveService do
Chat::UserChatChannelMembership.where(chat_channel: channel, following: true).count, Chat::UserChatChannelMembership.where(chat_channel: channel, following: true).count,
).to eq(3) ).to eq(3)
start_archive start_archive
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
expect(@channel_archive.reload.complete?).to eq(true) expect(@channel_archive.reload.complete?).to eq(true)
expect( expect(
Chat::UserChatChannelMembership.where(chat_channel: channel, following: true).count, Chat::UserChatChannelMembership.where(chat_channel: channel, following: true).count,
@ -243,7 +243,7 @@ describe Chat::ChannelArchiveService do
last_read_message_id: channel.chat_messages.first.id, last_read_message_id: channel.chat_messages.first.id,
) )
start_archive start_archive
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
expect(@channel_archive.reload.complete?).to eq(true) expect(@channel_archive.reload.complete?).to eq(true)
expect(Chat::UserChatChannelMembership.last.last_read_message_id).to eq( expect(Chat::UserChatChannelMembership.last.last_read_message_id).to eq(
channel.chat_messages.last.id, channel.chat_messages.last.id,
@ -257,7 +257,7 @@ describe Chat::ChannelArchiveService do
it "archives the topic" do it "archives the topic" do
create_messages(3) && start_archive create_messages(3) && start_archive
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
topic = @channel_archive.destination_topic topic = @channel_archive.destination_topic
topic.reload topic.reload
expect(topic.archived).to eq(true) expect(topic.archived).to eq(true)
@ -269,7 +269,7 @@ describe Chat::ChannelArchiveService do
it "leaves the topic open" do it "leaves the topic open" do
create_messages(3) && start_archive create_messages(3) && start_archive
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
topic = @channel_archive.destination_topic topic = @channel_archive.destination_topic
topic.reload topic.reload
expect(topic.archived).to eq(false) expect(topic.archived).to eq(false)
@ -282,7 +282,7 @@ describe Chat::ChannelArchiveService do
it "closes the topic" do it "closes the topic" do
create_messages(3) && start_archive create_messages(3) && start_archive
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
topic = @channel_archive.destination_topic topic = @channel_archive.destination_topic
topic.reload topic.reload
expect(topic.archived).to eq(false) expect(topic.archived).to eq(false)
@ -297,7 +297,7 @@ describe Chat::ChannelArchiveService do
destination_topic_title: nil, destination_topic_title: nil,
destination_topic_id: Fabricate(:topic).id, destination_topic_id: Fabricate(:topic).id,
) )
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
topic = @channel_archive.destination_topic topic = @channel_archive.destination_topic
topic.reload topic.reload
expect(topic.archived).to eq(false) expect(topic.archived).to eq(false)
@ -322,7 +322,7 @@ describe Chat::ChannelArchiveService do
emoji: "+1", emoji: "+1",
) )
stub_const(Chat::ChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do stub_const(Chat::ChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
end end
@channel_archive.reload @channel_archive.reload
@ -363,7 +363,7 @@ describe Chat::ChannelArchiveService do
.raises(FakeArchiveError.new("this is a test error")) .raises(FakeArchiveError.new("this is a test error"))
stub_const(Chat::ChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do stub_const(Chat::ChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do
expect { subject.new(@channel_archive).execute }.to raise_error(FakeArchiveError) expect { described_class.new(@channel_archive).execute }.to raise_error(FakeArchiveError)
end end
expect(@channel_archive.reload.archive_error).to eq("this is a test error") expect(@channel_archive.reload.archive_error).to eq("this is a test error")
@ -376,7 +376,7 @@ describe Chat::ChannelArchiveService do
Chat::ChannelArchiveService.any_instance.unstub(:create_post) Chat::ChannelArchiveService.any_instance.unstub(:create_post)
stub_const(Chat::ChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do stub_const(Chat::ChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do
subject.new(@channel_archive).execute described_class.new(@channel_archive).execute
end end
@channel_archive.reload @channel_archive.reload

View File

@ -3,6 +3,8 @@
require "rails_helper" require "rails_helper"
describe Chat::MessageBookmarkable do describe Chat::MessageBookmarkable do
subject(:registered_bookmarkable) { RegisteredBookmarkable.new(described_class) }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
fab!(:guardian) { Guardian.new(user) } fab!(:guardian) { Guardian.new(user) }
fab!(:other_category) { Fabricate(:private_category, group: Fabricate(:group)) } fab!(:other_category) { Fabricate(:private_category, group: Fabricate(:group)) }
@ -25,23 +27,21 @@ describe Chat::MessageBookmarkable do
let!(:bookmark2) { Fabricate(:bookmark, user: user, bookmarkable: message2) } let!(:bookmark2) { Fabricate(:bookmark, user: user, bookmarkable: message2) }
let!(:bookmark3) { Fabricate(:bookmark) } let!(:bookmark3) { Fabricate(:bookmark) }
subject { RegisteredBookmarkable.new(described_class) }
describe "#perform_list_query" do describe "#perform_list_query" do
it "returns all the user's bookmarks" do it "returns all the user's bookmarks" do
expect(subject.perform_list_query(user, guardian).map(&:id)).to match_array( expect(registered_bookmarkable.perform_list_query(user, guardian).map(&:id)).to match_array(
[bookmark1.id, bookmark2.id], [bookmark1.id, bookmark2.id],
) )
end end
it "does not return bookmarks for messages inside category chat channels the user cannot access" do it "does not return bookmarks for messages inside category chat channels the user cannot access" do
channel.update(chatable: other_category) channel.update(chatable: other_category)
expect(subject.perform_list_query(user, guardian)).to eq(nil) expect(registered_bookmarkable.perform_list_query(user, guardian)).to eq(nil)
other_category.groups.last.add(user) other_category.groups.last.add(user)
bookmark1.reload bookmark1.reload
user.reload user.reload
guardian = Guardian.new(user) guardian = Guardian.new(user)
expect(subject.perform_list_query(user, guardian).map(&:id)).to match_array( expect(registered_bookmarkable.perform_list_query(user, guardian).map(&:id)).to match_array(
[bookmark1.id, bookmark2.id], [bookmark1.id, bookmark2.id],
) )
end end
@ -49,12 +49,12 @@ describe Chat::MessageBookmarkable do
it "does not return bookmarks for messages inside direct message chat channels the user cannot access" do it "does not return bookmarks for messages inside direct message chat channels the user cannot access" do
direct_message = Fabricate(:direct_message) direct_message = Fabricate(:direct_message)
channel.update(chatable: direct_message) channel.update(chatable: direct_message)
expect(subject.perform_list_query(user, guardian)).to eq(nil) expect(registered_bookmarkable.perform_list_query(user, guardian)).to eq(nil)
Chat::DirectMessageUser.create(user: user, direct_message: direct_message) Chat::DirectMessageUser.create(user: user, direct_message: direct_message)
bookmark1.reload bookmark1.reload
user.reload user.reload
guardian = Guardian.new(user) guardian = Guardian.new(user)
expect(subject.perform_list_query(user, guardian).map(&:id)).to match_array( expect(registered_bookmarkable.perform_list_query(user, guardian).map(&:id)).to match_array(
[bookmark1.id, bookmark2.id], [bookmark1.id, bookmark2.id],
) )
end end
@ -62,7 +62,9 @@ describe Chat::MessageBookmarkable do
it "does not return bookmarks for deleted messages" do it "does not return bookmarks for deleted messages" do
message1.trash! message1.trash!
guardian = Guardian.new(user) guardian = Guardian.new(user)
expect(subject.perform_list_query(user, guardian).map(&:id)).to match_array([bookmark2.id]) expect(registered_bookmarkable.perform_list_query(user, guardian).map(&:id)).to match_array(
[bookmark2.id],
)
end end
end end
@ -72,8 +74,8 @@ describe Chat::MessageBookmarkable do
it "returns bookmarks that match by name" do it "returns bookmarks that match by name" do
ts_query = Search.ts_query(term: "gotta", ts_config: "simple") ts_query = Search.ts_query(term: "gotta", ts_config: "simple")
expect( expect(
subject.perform_search_query( registered_bookmarkable.perform_search_query(
subject.perform_list_query(user, guardian), registered_bookmarkable.perform_list_query(user, guardian),
"%gotta%", "%gotta%",
ts_query, ts_query,
).map(&:id), ).map(&:id),
@ -85,8 +87,8 @@ describe Chat::MessageBookmarkable do
ts_query = Search.ts_query(term: "good soup", ts_config: "simple") ts_query = Search.ts_query(term: "good soup", ts_config: "simple")
expect( expect(
subject.perform_search_query( registered_bookmarkable.perform_search_query(
subject.perform_list_query(user, guardian), registered_bookmarkable.perform_list_query(user, guardian),
"%good soup%", "%good soup%",
ts_query, ts_query,
).map(&:id), ).map(&:id),
@ -94,8 +96,8 @@ describe Chat::MessageBookmarkable do
ts_query = Search.ts_query(term: "blah", ts_config: "simple") ts_query = Search.ts_query(term: "blah", ts_config: "simple")
expect( expect(
subject.perform_search_query( registered_bookmarkable.perform_search_query(
subject.perform_list_query(user, guardian), registered_bookmarkable.perform_list_query(user, guardian),
"%blah%", "%blah%",
ts_query, ts_query,
).map(&:id), ).map(&:id),
@ -105,23 +107,23 @@ describe Chat::MessageBookmarkable do
describe "#can_send_reminder?" do describe "#can_send_reminder?" do
it "cannot send the reminder if the message or channel is deleted" do it "cannot send the reminder if the message or channel is deleted" do
expect(subject.can_send_reminder?(bookmark1)).to eq(true) expect(registered_bookmarkable.can_send_reminder?(bookmark1)).to eq(true)
bookmark1.bookmarkable.trash! bookmark1.bookmarkable.trash!
bookmark1.reload bookmark1.reload
expect(subject.can_send_reminder?(bookmark1)).to eq(false) expect(registered_bookmarkable.can_send_reminder?(bookmark1)).to eq(false)
Chat::Message.with_deleted.find_by(id: bookmark1.bookmarkable_id).recover! Chat::Message.with_deleted.find_by(id: bookmark1.bookmarkable_id).recover!
bookmark1.reload bookmark1.reload
bookmark1.bookmarkable.chat_channel.trash! bookmark1.bookmarkable.chat_channel.trash!
bookmark1.reload bookmark1.reload
expect(subject.can_send_reminder?(bookmark1)).to eq(false) expect(registered_bookmarkable.can_send_reminder?(bookmark1)).to eq(false)
end end
end end
describe "#reminder_handler" do describe "#reminder_handler" do
it "creates a notification for the user with the correct details" do it "creates a notification for the user with the correct details" do
expect { subject.send_reminder_notification(bookmark1) }.to change { Notification.count }.by( expect { registered_bookmarkable.send_reminder_notification(bookmark1) }.to change {
1, Notification.count
) }.by(1)
notification = user.notifications.last notification = user.notifications.last
expect(notification.notification_type).to eq(Notification.types[:bookmark_reminder]) expect(notification.notification_type).to eq(Notification.types[:bookmark_reminder])
expect(notification.data).to eq( expect(notification.data).to eq(
@ -142,38 +144,44 @@ describe Chat::MessageBookmarkable do
describe "#can_see?" do describe "#can_see?" do
it "returns false if the chat message is in a channel the user cannot see" do it "returns false if the chat message is in a channel the user cannot see" do
expect(subject.can_see?(guardian, bookmark1)).to eq(true) expect(registered_bookmarkable.can_see?(guardian, bookmark1)).to eq(true)
bookmark1.bookmarkable.chat_channel.update!(chatable: private_category) bookmark1.bookmarkable.chat_channel.update!(chatable: private_category)
expect(subject.can_see?(guardian, bookmark1)).to eq(false) expect(registered_bookmarkable.can_see?(guardian, bookmark1)).to eq(false)
private_category.groups.last.add(user) private_category.groups.last.add(user)
bookmark1.reload bookmark1.reload
user.reload user.reload
guardian = Guardian.new(user) guardian = Guardian.new(user)
expect(subject.can_see?(guardian, bookmark1)).to eq(true) expect(registered_bookmarkable.can_see?(guardian, bookmark1)).to eq(true)
end end
end end
describe "#validate_before_create" do describe "#validate_before_create" do
it "raises InvalidAccess if the user cannot see the chat channel" do it "raises InvalidAccess if the user cannot see the chat channel" do
expect { subject.validate_before_create(guardian, bookmark1.bookmarkable) }.not_to raise_error expect {
registered_bookmarkable.validate_before_create(guardian, bookmark1.bookmarkable)
}.not_to raise_error
bookmark1.bookmarkable.chat_channel.update!(chatable: private_category) bookmark1.bookmarkable.chat_channel.update!(chatable: private_category)
expect { subject.validate_before_create(guardian, bookmark1.bookmarkable) }.to raise_error( expect {
Discourse::InvalidAccess, registered_bookmarkable.validate_before_create(guardian, bookmark1.bookmarkable)
) }.to raise_error(Discourse::InvalidAccess)
private_category.groups.last.add(user) private_category.groups.last.add(user)
bookmark1.reload bookmark1.reload
user.reload user.reload
guardian = Guardian.new(user) guardian = Guardian.new(user)
expect { subject.validate_before_create(guardian, bookmark1.bookmarkable) }.not_to raise_error expect {
registered_bookmarkable.validate_before_create(guardian, bookmark1.bookmarkable)
}.not_to raise_error
end end
it "raises InvalidAccess if the chat message is deleted" do it "raises InvalidAccess if the chat message is deleted" do
expect { subject.validate_before_create(guardian, bookmark1.bookmarkable) }.not_to raise_error expect {
registered_bookmarkable.validate_before_create(guardian, bookmark1.bookmarkable)
}.not_to raise_error
bookmark1.bookmarkable.trash! bookmark1.bookmarkable.trash!
bookmark1.reload bookmark1.reload
expect { subject.validate_before_create(guardian, bookmark1.bookmarkable) }.to raise_error( expect {
Discourse::InvalidAccess, registered_bookmarkable.validate_before_create(guardian, bookmark1.bookmarkable)
) }.to raise_error(Discourse::InvalidAccess)
end end
end end
@ -182,7 +190,7 @@ describe Chat::MessageBookmarkable do
bookmark_post = Fabricate(:bookmark, bookmarkable: Fabricate(:post)) bookmark_post = Fabricate(:bookmark, bookmarkable: Fabricate(:post))
bookmark1.bookmarkable.trash! bookmark1.bookmarkable.trash!
bookmark1.bookmarkable.update!(deleted_at: 4.days.ago) bookmark1.bookmarkable.update!(deleted_at: 4.days.ago)
subject.cleanup_deleted registered_bookmarkable.cleanup_deleted
expect(Bookmark.exists?(id: bookmark1.id)).to eq(false) expect(Bookmark.exists?(id: bookmark1.id)).to eq(false)
expect(Bookmark.exists?(id: bookmark2.id)).to eq(true) expect(Bookmark.exists?(id: bookmark2.id)).to eq(true)
expect(Bookmark.exists?(id: bookmark_post.id)).to eq(true) expect(Bookmark.exists?(id: bookmark_post.id)).to eq(true)

View File

@ -3,39 +3,40 @@
require "rails_helper" require "rails_helper"
describe Chat::MessageReactor do describe Chat::MessageReactor do
subject(:message_reactor) { described_class.new(reacting_user, channel) }
fab!(:reacting_user) { Fabricate(:user) } fab!(:reacting_user) { Fabricate(:user) }
fab!(:channel) { Fabricate(:category_channel) } fab!(:channel) { Fabricate(:category_channel) }
fab!(:reactor) { described_class.new(reacting_user, channel) } fab!(:reactor) { described_class.new(reacting_user, channel) }
fab!(:message_1) { Fabricate(:chat_message, chat_channel: channel, user: reacting_user) } fab!(:message_1) { Fabricate(:chat_message, chat_channel: channel, user: reacting_user) }
let(:subject) { described_class.new(reacting_user, channel) }
it "calls guardian ensure_can_join_chat_channel!" do it "calls guardian ensure_can_join_chat_channel!" do
Guardian.any_instance.expects(:ensure_can_join_chat_channel!).once Guardian.any_instance.expects(:ensure_can_join_chat_channel!).once
subject.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:") message_reactor.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:")
end end
it "raises an error if the user cannot see the channel" do it "raises an error if the user cannot see the channel" do
channel.update!(chatable: Fabricate(:private_category, group: Group[:staff])) channel.update!(chatable: Fabricate(:private_category, group: Group[:staff]))
expect { expect {
subject.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:") message_reactor.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:")
}.to raise_error(Discourse::InvalidAccess) }.to raise_error(Discourse::InvalidAccess)
end end
it "raises an error if the user cannot react" do it "raises an error if the user cannot react" do
SpamRule::AutoSilence.new(reacting_user).silence_user SpamRule::AutoSilence.new(reacting_user).silence_user
expect { expect {
subject.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:") message_reactor.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:")
}.to raise_error(Discourse::InvalidAccess) }.to raise_error(Discourse::InvalidAccess)
end end
it "raises an error if the channel status is not open" do it "raises an error if the channel status is not open" do
channel.update!(status: Chat::Channel.statuses[:archived]) channel.update!(status: Chat::Channel.statuses[:archived])
expect { expect {
subject.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:") message_reactor.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:")
}.to raise_error(Discourse::InvalidAccess) }.to raise_error(Discourse::InvalidAccess)
channel.update!(status: Chat::Channel.statuses[:open]) channel.update!(status: Chat::Channel.statuses[:open])
expect { expect {
subject.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:") message_reactor.react!(message_id: message_1.id, react_action: :add, emoji: ":+1:")
}.to change(Chat::MessageReaction, :count).by(1) }.to change(Chat::MessageReaction, :count).by(1)
end end

View File

@ -3,10 +3,11 @@
require "rails_helper" require "rails_helper"
describe Chat::PostNotificationHandler do describe Chat::PostNotificationHandler do
subject(:handler) { described_class.new(post, notified_users) }
let(:acting_user) { Fabricate(:user) } let(:acting_user) { Fabricate(:user) }
let(:post) { Fabricate(:post) } let(:post) { Fabricate(:post) }
let(:notified_users) { [] } let(:notified_users) { [] }
let(:subject) { described_class.new(post, notified_users) }
fab!(:channel) { Fabricate(:category_channel) } fab!(:channel) { Fabricate(:category_channel) }
fab!(:message1) do fab!(:message1) do
@ -24,7 +25,7 @@ describe Chat::PostNotificationHandler do
def expect_no_notification def expect_no_notification
return_val = nil return_val = nil
expect { return_val = subject.handle }.not_to change { Notification.count } expect { return_val = handler.handle }.not_to change { Notification.count }
expect(return_val).to eq(false) expect(return_val).to eq(false)
end end
@ -51,7 +52,7 @@ describe Chat::PostNotificationHandler do
it "sends notifications to all of the quoted users" do it "sends notifications to all of the quoted users" do
update_post_with_chat_quote([message1, message2]) update_post_with_chat_quote([message1, message2])
subject.handle handler.handle
expect( expect(
Notification.where( Notification.where(
user: message1.user, user: message1.user,
@ -68,8 +69,8 @@ describe Chat::PostNotificationHandler do
it "does not send the same chat_quoted notification twice to the same post and user" do it "does not send the same chat_quoted notification twice to the same post and user" do
update_post_with_chat_quote([message1, message2]) update_post_with_chat_quote([message1, message2])
subject.handle handler.handle
subject.handle handler.handle
expect( expect(
Notification.where( Notification.where(
user: message1.user, user: message1.user,
@ -87,7 +88,7 @@ describe Chat::PostNotificationHandler do
topic: post.topic, topic: post.topic,
user: message1.user, user: message1.user,
) )
subject.handle handler.handle
expect( expect(
Notification.where( Notification.where(
user: message1.user, user: message1.user,
@ -101,7 +102,7 @@ describe Chat::PostNotificationHandler do
it "does not send notifications to those users" do it "does not send notifications to those users" do
update_post_with_chat_quote([message1, message2]) update_post_with_chat_quote([message1, message2])
subject.handle handler.handle
expect( expect(
Notification.where( Notification.where(
user: message1.user, user: message1.user,

View File

@ -3,17 +3,17 @@
require "rails_helper" require "rails_helper"
describe Chat::ReviewQueue do describe Chat::ReviewQueue do
subject(:queue) { described_class.new }
fab!(:message_poster) { Fabricate(:user) } fab!(:message_poster) { Fabricate(:user) }
fab!(:flagger) { Fabricate(:user) } fab!(:flagger) { Fabricate(:user) }
fab!(:chat_channel) { Fabricate(:category_channel) } fab!(:chat_channel) { Fabricate(:category_channel) }
fab!(:message) { Fabricate(:chat_message, user: message_poster, chat_channel: chat_channel) } fab!(:message) { Fabricate(:chat_message, user: message_poster, chat_channel: chat_channel) }
fab!(:admin) { Fabricate(:admin) } fab!(:admin) { Fabricate(:admin) }
let(:guardian) { Guardian.new(flagger) } let(:guardian) { Guardian.new(flagger) }
let(:admin_guardian) { Guardian.new(admin) } let(:admin_guardian) { Guardian.new(admin) }
subject(:queue) { described_class.new }
before do before do
chat_channel.add(message_poster) chat_channel.add(message_poster)
chat_channel.add(flagger) chat_channel.add(flagger)

View File

@ -3,15 +3,19 @@
require "rails_helper" require "rails_helper"
describe Chat::DeletedUser do describe Chat::DeletedUser do
subject(:deleted_user) { described_class.new }
describe "#username" do describe "#username" do
it "returns a default username" do it "returns a default username" do
expect(subject.username).to eq(I18n.t("chat.deleted_chat_username")) expect(deleted_user.username).to eq(I18n.t("chat.deleted_chat_username"))
end end
end end
describe "#avatar_template" do describe "#avatar_template" do
it "returns a default path" do it "returns a default path" do
expect(subject.avatar_template).to eq("/plugins/chat/images/deleted-chat-user-avatar.png") expect(deleted_user.avatar_template).to eq(
"/plugins/chat/images/deleted-chat-user-avatar.png",
)
end end
end end
end end

View File

@ -3,6 +3,15 @@
require "rails_helper" require "rails_helper"
describe Chat::ChannelUnreadsQuery do describe Chat::ChannelUnreadsQuery do
subject(:query) do
described_class.call(
channel_ids: channel_ids,
user_id: current_user.id,
include_missing_memberships: include_missing_memberships,
include_read: include_read,
).map(&:to_h)
end
fab!(:channel_1) { Fabricate(:category_channel) } fab!(:channel_1) { Fabricate(:category_channel) }
fab!(:current_user) { Fabricate(:user) } fab!(:current_user) { Fabricate(:user) }
let(:include_missing_memberships) { false } let(:include_missing_memberships) { false }
@ -15,20 +24,11 @@ describe Chat::ChannelUnreadsQuery do
channel_1.add(current_user) channel_1.add(current_user)
end end
let(:subject) do
described_class.call(
channel_ids: channel_ids,
user_id: current_user.id,
include_missing_memberships: include_missing_memberships,
include_read: include_read,
).map(&:to_h)
end
context "with unread message" do context "with unread message" do
before { Fabricate(:chat_message, chat_channel: channel_1) } before { Fabricate(:chat_message, chat_channel: channel_1) }
it "returns a correct unread count" do it "returns a correct unread count" do
expect(subject.first).to eq({ mention_count: 0, unread_count: 1, channel_id: channel_1.id }) expect(query.first).to eq({ mention_count: 0, unread_count: 1, channel_id: channel_1.id })
end end
context "when the membership has been muted" do context "when the membership has been muted" do
@ -40,7 +40,7 @@ describe Chat::ChannelUnreadsQuery do
end end
it "returns a zeroed unread count" do it "returns a zeroed unread count" do
expect(subject.first).to eq({ mention_count: 0, unread_count: 0, channel_id: channel_1.id }) expect(query.first).to eq({ mention_count: 0, unread_count: 0, channel_id: channel_1.id })
end end
end end
@ -49,13 +49,13 @@ describe Chat::ChannelUnreadsQuery do
fab!(:thread) { Fabricate(:chat_thread, channel: channel_1, original_message: thread_om) } fab!(:thread) { Fabricate(:chat_thread, channel: channel_1, original_message: thread_om) }
it "does include the original message in the unread count" do it "does include the original message in the unread count" do
expect(subject.first).to eq({ mention_count: 0, unread_count: 2, channel_id: channel_1.id }) expect(query.first).to eq({ mention_count: 0, unread_count: 2, channel_id: channel_1.id })
end end
it "does not include other thread messages in the unread count" do it "does not include other thread messages in the unread count" do
Fabricate(:chat_message, chat_channel: channel_1, thread: thread) Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
Fabricate(:chat_message, chat_channel: channel_1, thread: thread) Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
expect(subject.first).to eq({ mention_count: 0, unread_count: 2, channel_id: channel_1.id }) expect(query.first).to eq({ mention_count: 0, unread_count: 2, channel_id: channel_1.id })
end end
end end
@ -70,7 +70,7 @@ describe Chat::ChannelUnreadsQuery do
end end
it "returns accurate counts" do it "returns accurate counts" do
expect(subject).to match_array( expect(query).to match_array(
[ [
{ mention_count: 0, unread_count: 1, channel_id: channel_1.id }, { mention_count: 0, unread_count: 1, channel_id: channel_1.id },
{ mention_count: 0, unread_count: 2, channel_id: channel_2.id }, { mention_count: 0, unread_count: 2, channel_id: channel_2.id },
@ -87,7 +87,7 @@ describe Chat::ChannelUnreadsQuery do
end end
it "does not return counts for the channels" do it "does not return counts for the channels" do
expect(subject).to match_array( expect(query).to match_array(
[{ mention_count: 0, unread_count: 1, channel_id: channel_1.id }], [{ mention_count: 0, unread_count: 1, channel_id: channel_1.id }],
) )
end end
@ -96,7 +96,7 @@ describe Chat::ChannelUnreadsQuery do
let(:include_missing_memberships) { true } let(:include_missing_memberships) { true }
it "does return zeroed counts for the channels" do it "does return zeroed counts for the channels" do
expect(subject).to match_array( expect(query).to match_array(
[ [
{ mention_count: 0, unread_count: 1, channel_id: channel_1.id }, { mention_count: 0, unread_count: 1, channel_id: channel_1.id },
{ mention_count: 0, unread_count: 0, channel_id: channel_2.id }, { mention_count: 0, unread_count: 0, channel_id: channel_2.id },
@ -108,7 +108,7 @@ describe Chat::ChannelUnreadsQuery do
let(:include_read) { false } let(:include_read) { false }
it "does not return counts for the channels" do it "does not return counts for the channels" do
expect(subject).to match_array( expect(query).to match_array(
[{ mention_count: 0, unread_count: 1, channel_id: channel_1.id }], [{ mention_count: 0, unread_count: 1, channel_id: channel_1.id }],
) )
end end
@ -135,7 +135,7 @@ describe Chat::ChannelUnreadsQuery do
message = Fabricate(:chat_message, chat_channel: channel_1) message = Fabricate(:chat_message, chat_channel: channel_1)
create_mention(message, channel_1) create_mention(message, channel_1)
expect(subject.first).to eq({ mention_count: 1, unread_count: 1, channel_id: channel_1.id }) expect(query.first).to eq({ mention_count: 1, unread_count: 1, channel_id: channel_1.id })
end end
context "for unread mentions in a thread" do context "for unread mentions in a thread" do
@ -144,7 +144,7 @@ describe Chat::ChannelUnreadsQuery do
it "does include the original message in the mention count" do it "does include the original message in the mention count" do
create_mention(thread_om, channel_1) create_mention(thread_om, channel_1)
expect(subject.first).to eq({ mention_count: 1, unread_count: 1, channel_id: channel_1.id }) expect(query.first).to eq({ mention_count: 1, unread_count: 1, channel_id: channel_1.id })
end end
it "does not include other thread messages in the mention count" do it "does not include other thread messages in the mention count" do
@ -152,7 +152,7 @@ describe Chat::ChannelUnreadsQuery do
thread_message_2 = Fabricate(:chat_message, chat_channel: channel_1, thread: thread) thread_message_2 = Fabricate(:chat_message, chat_channel: channel_1, thread: thread)
create_mention(thread_message_1, channel_1) create_mention(thread_message_1, channel_1)
create_mention(thread_message_2, channel_1) create_mention(thread_message_2, channel_1)
expect(subject.first).to eq({ mention_count: 0, unread_count: 1, channel_id: channel_1.id }) expect(query.first).to eq({ mention_count: 0, unread_count: 1, channel_id: channel_1.id })
end end
end end
@ -169,7 +169,7 @@ describe Chat::ChannelUnreadsQuery do
message_2 = Fabricate(:chat_message, chat_channel: channel_2) message_2 = Fabricate(:chat_message, chat_channel: channel_2)
create_mention(message_2, channel_2) create_mention(message_2, channel_2)
expect(subject).to match_array( expect(query).to match_array(
[ [
{ mention_count: 1, unread_count: 1, channel_id: channel_1.id }, { mention_count: 1, unread_count: 1, channel_id: channel_1.id },
{ mention_count: 1, unread_count: 2, channel_id: channel_2.id }, { mention_count: 1, unread_count: 2, channel_id: channel_2.id },
@ -181,14 +181,14 @@ describe Chat::ChannelUnreadsQuery do
context "with nothing unread" do context "with nothing unread" do
it "returns a correct state" do it "returns a correct state" do
expect(subject.first).to eq({ mention_count: 0, unread_count: 0, channel_id: channel_1.id }) expect(query.first).to eq({ mention_count: 0, unread_count: 0, channel_id: channel_1.id })
end end
context "when include_read is false" do context "when include_read is false" do
let(:include_read) { false } let(:include_read) { false }
it "returns nothing" do it "returns nothing" do
expect(subject).to eq([]) expect(query).to eq([])
end end
end end
end end

View File

@ -1,6 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Chat::MessagesQuery do RSpec.describe Chat::MessagesQuery do
subject(:query) do
described_class.call(guardian: current_user.guardian, channel: channel, **options)
end
fab!(:channel) { Fabricate(:category_channel) } fab!(:channel) { Fabricate(:category_channel) }
fab!(:current_user) { Fabricate(:user) } fab!(:current_user) { Fabricate(:user) }
@ -21,10 +25,6 @@ RSpec.describe Chat::MessagesQuery do
} }
end end
let(:subject) do
described_class.call(guardian: current_user.guardian, channel: channel, **options)
end
fab!(:message_1) do fab!(:message_1) do
message = Fabricate(:chat_message, chat_channel: channel) message = Fabricate(:chat_message, chat_channel: channel)
message.update!(created_at: 2.days.ago) message.update!(created_at: 2.days.ago)
@ -42,7 +42,7 @@ RSpec.describe Chat::MessagesQuery do
let(:target_message_id) { target_message.id } let(:target_message_id) { target_message.id }
it "queries messages in the channel and finds the past and future messages" do it "queries messages in the channel and finds the past and future messages" do
expect(subject).to eq( expect(query).to eq(
past_messages: [message_1], past_messages: [message_1],
future_messages: [message_3], future_messages: [message_3],
target_message: target_message, target_message: target_message,
@ -53,29 +53,29 @@ RSpec.describe Chat::MessagesQuery do
it "does not include deleted messages" do it "does not include deleted messages" do
message_3.trash! message_3.trash!
expect(subject[:future_messages]).to eq([]) expect(query[:future_messages]).to eq([])
end end
it "still includes the target message if it is deleted" do it "still includes the target message if it is deleted" do
target_message.trash! target_message.trash!
expect(subject[:target_message]).to eq(target_message) expect(query[:target_message]).to eq(target_message)
end end
it "can_load_more_past is true when the past messages reach the limit" do it "can_load_more_past is true when the past messages reach the limit" do
stub_const(described_class, "PAST_MESSAGE_LIMIT", 1) do stub_const(described_class, "PAST_MESSAGE_LIMIT", 1) do
expect(subject[:can_load_more_past]).to be_truthy expect(query[:can_load_more_past]).to be_truthy
end end
end end
it "can_load_more_future is true when the future messages reach the limit" do it "can_load_more_future is true when the future messages reach the limit" do
stub_const(described_class, "FUTURE_MESSAGE_LIMIT", 1) do stub_const(described_class, "FUTURE_MESSAGE_LIMIT", 1) do
expect(subject[:can_load_more_future]).to be_truthy expect(query[:can_load_more_future]).to be_truthy
end end
end end
it "limits results of paginated query when page_size is not set" do it "limits results of paginated query when page_size is not set" do
options[:target_message_id] = nil options[:target_message_id] = nil
stub_const(described_class, "MAX_PAGE_SIZE", 1) { expect(subject[:messages].length).to eq(1) } stub_const(described_class, "MAX_PAGE_SIZE", 1) { expect(query[:messages].length).to eq(1) }
end end
describe "when some messages are in threads" do describe "when some messages are in threads" do
@ -83,7 +83,7 @@ RSpec.describe Chat::MessagesQuery do
it "does not include messages which are thread replies but does include thread original messages" do it "does not include messages which are thread replies but does include thread original messages" do
message_3.update!(thread: thread) message_3.update!(thread: thread)
expect(subject[:future_messages]).to eq([thread.original_message]) expect(query[:future_messages]).to eq([thread.original_message])
end end
context "when include_thread_messages is true" do context "when include_thread_messages is true" do
@ -94,7 +94,7 @@ RSpec.describe Chat::MessagesQuery do
thread: thread, thread: thread,
created_at: thread.original_message.created_at + 1.minute, created_at: thread.original_message.created_at + 1.minute,
) )
expect(subject[:future_messages]).to eq([thread.original_message, message_3]) expect(query[:future_messages]).to eq([thread.original_message, message_3])
end end
end end
@ -105,7 +105,7 @@ RSpec.describe Chat::MessagesQuery do
thread: thread, thread: thread,
created_at: thread.original_message.created_at + 1.minute, created_at: thread.original_message.created_at + 1.minute,
) )
expect(subject[:future_messages]).to eq([thread.original_message, message_3]) expect(query[:future_messages]).to eq([thread.original_message, message_3])
end end
end end
end end
@ -115,7 +115,7 @@ RSpec.describe Chat::MessagesQuery do
it "does include deleted messages" do it "does include deleted messages" do
message_3.trash! message_3.trash!
expect(subject[:future_messages]).to eq([message_3]) expect(query[:future_messages]).to eq([message_3])
end end
end end
end end
@ -124,7 +124,7 @@ RSpec.describe Chat::MessagesQuery do
let(:target_date) { 1.day.ago } let(:target_date) { 1.day.ago }
it "queries messages in the channel and finds the past and future messages" do it "queries messages in the channel and finds the past and future messages" do
expect(subject).to eq( expect(query).to eq(
past_messages: [message_1], past_messages: [message_1],
future_messages: [message_2, message_3], future_messages: [message_2, message_3],
target_date: target_date, target_date: target_date,
@ -136,7 +136,7 @@ RSpec.describe Chat::MessagesQuery do
context "when target_message_id not provided" do context "when target_message_id not provided" do
it "queries messages in the channel" do it "queries messages in the channel" do
expect(subject).to eq( expect(query).to eq(
messages: [message_1, message_2, message_3], messages: [message_1, message_2, message_3],
can_load_more_past: false, can_load_more_past: false,
can_load_more_future: false, can_load_more_future: false,
@ -147,7 +147,7 @@ RSpec.describe Chat::MessagesQuery do
let(:page_size) { 3 } let(:page_size) { 3 }
it "can_load_more_past is true" do it "can_load_more_past is true" do
expect(subject[:can_load_more_past]).to be_truthy expect(query[:can_load_more_past]).to be_truthy
end end
end end
@ -155,14 +155,14 @@ RSpec.describe Chat::MessagesQuery do
let(:direction) { described_class::FUTURE } let(:direction) { described_class::FUTURE }
it "returns messages in ascending order by created_at" do it "returns messages in ascending order by created_at" do
expect(subject[:messages]).to eq([message_1, message_2, message_3]) expect(query[:messages]).to eq([message_1, message_2, message_3])
end end
context "when the messages length is equal to the page_size" do context "when the messages length is equal to the page_size" do
let(:page_size) { 3 } let(:page_size) { 3 }
it "can_load_more_future is true" do it "can_load_more_future is true" do
expect(subject[:can_load_more_future]).to be_truthy expect(query[:can_load_more_future]).to be_truthy
end end
end end
end end
@ -171,14 +171,14 @@ RSpec.describe Chat::MessagesQuery do
let(:direction) { described_class::PAST } let(:direction) { described_class::PAST }
it "returns messages in ascending order by created_at" do it "returns messages in ascending order by created_at" do
expect(subject[:messages]).to eq([message_1, message_2, message_3]) expect(query[:messages]).to eq([message_1, message_2, message_3])
end end
context "when the messages length is equal to the page_size" do context "when the messages length is equal to the page_size" do
let(:page_size) { 3 } let(:page_size) { 3 }
it "can_load_more_past is true" do it "can_load_more_past is true" do
expect(subject[:can_load_more_past]).to be_truthy expect(query[:can_load_more_past]).to be_truthy
end end
end end
end end

View File

@ -3,6 +3,16 @@
require "rails_helper" require "rails_helper"
describe Chat::ThreadUnreadsQuery do describe Chat::ThreadUnreadsQuery do
subject(:query) do
described_class.call(
channel_ids: channel_ids,
thread_ids: thread_ids,
user_id: current_user.id,
include_missing_memberships: include_missing_memberships,
include_read: include_read,
)
end
fab!(:channel_1) { Fabricate(:category_channel, threading_enabled: true) } fab!(:channel_1) { Fabricate(:category_channel, threading_enabled: true) }
fab!(:channel_2) { Fabricate(:category_channel, threading_enabled: true) } fab!(:channel_2) { Fabricate(:category_channel, threading_enabled: true) }
fab!(:thread_1) { Fabricate(:chat_thread, channel: channel_1) } fab!(:thread_1) { Fabricate(:chat_thread, channel: channel_1) }
@ -16,15 +26,6 @@ describe Chat::ThreadUnreadsQuery do
let(:include_read) { true } let(:include_read) { true }
let(:channel_ids) { [] } let(:channel_ids) { [] }
let(:thread_ids) { [] } let(:thread_ids) { [] }
let(:subject) do
described_class.call(
channel_ids: channel_ids,
thread_ids: thread_ids,
user_id: current_user.id,
include_missing_memberships: include_missing_memberships,
include_read: include_read,
)
end
before do before do
SiteSetting.chat_enabled = true SiteSetting.chat_enabled = true
@ -47,7 +48,7 @@ describe Chat::ThreadUnreadsQuery do
let(:channel_ids) { [channel_1.id, channel_2.id] } let(:channel_ids) { [channel_1.id, channel_2.id] }
it "gets a count of all the thread unreads across the channels" do it "gets a count of all the thread unreads across the channels" do
expect(subject.map(&:to_h)).to match_array( expect(query.map(&:to_h)).to match_array(
[ [
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 1 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 1 },
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_2.id, unread_count: 0 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_2.id, unread_count: 0 },
@ -59,17 +60,17 @@ describe Chat::ThreadUnreadsQuery do
it "does not count deleted messages" do it "does not count deleted messages" do
message_1.trash! message_1.trash!
expect(subject.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq( expect(query.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq(
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 },
) )
end end
it "does not messages in threads where threading_enabled is false on the channel" do it "does not messages in threads where threading_enabled is false on the channel" do
channel_1.update!(threading_enabled: false) channel_1.update!(threading_enabled: false)
expect(subject.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq( expect(query.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq(
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 },
) )
expect(subject.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_2.id }).to eq( expect(query.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_2.id }).to eq(
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_2.id, unread_count: 0 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_2.id, unread_count: 0 },
) )
end end
@ -79,7 +80,7 @@ describe Chat::ThreadUnreadsQuery do
.user_chat_thread_memberships .user_chat_thread_memberships
.find_by(user: current_user) .find_by(user: current_user)
.update!(last_read_message_id: message_1.id) .update!(last_read_message_id: message_1.id)
expect(subject.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq( expect(query.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq(
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 },
) )
end end
@ -87,7 +88,7 @@ describe Chat::ThreadUnreadsQuery do
it "does not count the original message ID as unread" do it "does not count the original message ID as unread" do
thread_1.original_message.destroy thread_1.original_message.destroy
thread_1.update!(original_message: message_1) thread_1.update!(original_message: message_1)
expect(subject.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq( expect(query.map(&:to_h).find { |tracking| tracking[:thread_id] == thread_1.id }).to eq(
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 },
) )
end end
@ -96,7 +97,7 @@ describe Chat::ThreadUnreadsQuery do
let(:include_read) { false } let(:include_read) { false }
it "does not get threads with no unread messages" do it "does not get threads with no unread messages" do
expect(subject.map(&:to_h)).not_to include( expect(query.map(&:to_h)).not_to include(
[ [
{ {
channel_id: channel_1.id, channel_id: channel_1.id,
@ -114,7 +115,7 @@ describe Chat::ThreadUnreadsQuery do
let(:thread_ids) { [thread_1.id, thread_3.id] } let(:thread_ids) { [thread_1.id, thread_3.id] }
it "gets a count of all the thread unreads for the specified threads" do it "gets a count of all the thread unreads for the specified threads" do
expect(subject.map(&:to_h)).to match_array( expect(query.map(&:to_h)).to match_array(
[ [
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 1 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 1 },
{ channel_id: channel_2.id, mention_count: 0, thread_id: thread_3.id, unread_count: 1 }, { channel_id: channel_2.id, mention_count: 0, thread_id: thread_3.id, unread_count: 1 },
@ -131,7 +132,7 @@ describe Chat::ThreadUnreadsQuery do
end end
it "gets a zeroed out count for the thread" do it "gets a zeroed out count for the thread" do
expect(subject.map(&:to_h)).to include( expect(query.map(&:to_h)).to include(
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 },
) )
end end
@ -146,7 +147,7 @@ describe Chat::ThreadUnreadsQuery do
end end
it "gets a zeroed out count for the thread" do it "gets a zeroed out count for the thread" do
expect(subject.map(&:to_h)).to include( expect(query.map(&:to_h)).to include(
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 0 },
) )
end end
@ -156,7 +157,7 @@ describe Chat::ThreadUnreadsQuery do
before { thread_1.user_chat_thread_memberships.find_by(user: current_user).destroy! } before { thread_1.user_chat_thread_memberships.find_by(user: current_user).destroy! }
it "does not get that thread unread count by default" do it "does not get that thread unread count by default" do
expect(subject.map(&:to_h)).to match_array( expect(query.map(&:to_h)).to match_array(
[ [
{ {
channel_id: channel_2.id, channel_id: channel_2.id,
@ -172,7 +173,7 @@ describe Chat::ThreadUnreadsQuery do
let(:include_missing_memberships) { true } let(:include_missing_memberships) { true }
it "includes the thread that the user is not a member of with zeroed out counts" do it "includes the thread that the user is not a member of with zeroed out counts" do
expect(subject.map(&:to_h)).to match_array( expect(query.map(&:to_h)).to match_array(
[ [
{ {
channel_id: channel_1.id, channel_id: channel_1.id,
@ -194,7 +195,7 @@ describe Chat::ThreadUnreadsQuery do
let(:include_read) { false } let(:include_read) { false }
it "does not include the thread that the user is not a member of with zeroed out counts" do it "does not include the thread that the user is not a member of with zeroed out counts" do
expect(subject.map(&:to_h)).to match_array( expect(query.map(&:to_h)).to match_array(
[ [
{ {
channel_id: channel_2.id, channel_id: channel_2.id,
@ -215,7 +216,7 @@ describe Chat::ThreadUnreadsQuery do
let(:thread_ids) { [thread_1.id, thread_3.id] } let(:thread_ids) { [thread_1.id, thread_3.id] }
it "gets a count of all the thread unreads across the channels filtered by thread id" do it "gets a count of all the thread unreads across the channels filtered by thread id" do
expect(subject.map(&:to_h)).to match_array( expect(query.map(&:to_h)).to match_array(
[ [
{ channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 1 }, { channel_id: channel_1.id, mention_count: 0, thread_id: thread_1.id, unread_count: 1 },
{ channel_id: channel_2.id, mention_count: 0, thread_id: thread_3.id, unread_count: 1 }, { channel_id: channel_2.id, mention_count: 0, thread_id: thread_3.id, unread_count: 1 },

View File

@ -1,15 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Chat::TrackingStateReportQuery do RSpec.describe Chat::TrackingStateReportQuery do
fab!(:current_user) { Fabricate(:user) } subject(:query) do
let(:guardian) { current_user.guardian }
let(:channel_ids) { [] }
let(:thread_ids) { [] }
let(:include_missing_memberships) { false }
let(:include_threads) { false }
let(:include_read) { true }
let(:subject) do
described_class.call( described_class.call(
guardian: guardian, guardian: guardian,
channel_ids: channel_ids, channel_ids: channel_ids,
@ -20,9 +12,17 @@ RSpec.describe Chat::TrackingStateReportQuery do
) )
end end
fab!(:current_user) { Fabricate(:user) }
let(:guardian) { current_user.guardian }
let(:channel_ids) { [] }
let(:thread_ids) { [] }
let(:include_missing_memberships) { false }
let(:include_threads) { false }
let(:include_read) { true }
context "when channel_ids empty" do context "when channel_ids empty" do
it "returns empty object for channel_tracking" do it "returns empty object for channel_tracking" do
expect(subject.channel_tracking).to eq({}) expect(query.channel_tracking).to eq({})
end end
end end
@ -41,7 +41,7 @@ RSpec.describe Chat::TrackingStateReportQuery do
include_read: include_read, include_read: include_read,
) )
.returns([]) .returns([])
subject query
end end
it "generates a correct unread report for the channels the user is a member of" do it "generates a correct unread report for the channels the user is a member of" do
@ -50,7 +50,7 @@ RSpec.describe Chat::TrackingStateReportQuery do
Fabricate(:chat_message, chat_channel: channel_1) Fabricate(:chat_message, chat_channel: channel_1)
Fabricate(:chat_message, chat_channel: channel_2) Fabricate(:chat_message, chat_channel: channel_2)
expect(subject.channel_tracking).to eq( expect(query.channel_tracking).to eq(
{ {
channel_1.id => { channel_1.id => {
unread_count: 1, unread_count: 1,
@ -66,7 +66,7 @@ RSpec.describe Chat::TrackingStateReportQuery do
it "does not include threads by default" do it "does not include threads by default" do
Chat::ThreadUnreadsQuery.expects(:call).never Chat::ThreadUnreadsQuery.expects(:call).never
expect(subject.thread_tracking).to eq({}) expect(query.thread_tracking).to eq({})
end end
context "when include_threads is true" do context "when include_threads is true" do
@ -90,7 +90,7 @@ RSpec.describe Chat::TrackingStateReportQuery do
include_read: include_read, include_read: include_read,
) )
.returns([]) .returns([])
subject query
end end
it "generates a correct unread for the threads the user is a member of in the channels" do it "generates a correct unread for the threads the user is a member of in the channels" do
@ -101,7 +101,7 @@ RSpec.describe Chat::TrackingStateReportQuery do
Fabricate(:chat_message, chat_channel: channel_1, thread: thread_1) Fabricate(:chat_message, chat_channel: channel_1, thread: thread_1)
Fabricate(:chat_message, chat_channel: channel_2, thread: thread_2) Fabricate(:chat_message, chat_channel: channel_2, thread: thread_2)
expect(subject.channel_tracking).to eq( expect(query.channel_tracking).to eq(
{ {
channel_1.id => { channel_1.id => {
unread_count: 1, unread_count: 1,
@ -113,7 +113,7 @@ RSpec.describe Chat::TrackingStateReportQuery do
}, },
}, },
) )
expect(subject.thread_tracking).to eq( expect(query.thread_tracking).to eq(
{ {
thread_1.id => { thread_1.id => {
unread_count: 1, unread_count: 1,
@ -135,7 +135,7 @@ RSpec.describe Chat::TrackingStateReportQuery do
it "does not query threads" do it "does not query threads" do
Chat::ThreadUnreadsQuery.expects(:call).never Chat::ThreadUnreadsQuery.expects(:call).never
expect(subject.thread_tracking).to eq({}) expect(query.thread_tracking).to eq({})
end end
end end
end end

View File

@ -3,23 +3,25 @@
require "rails_helper" require "rails_helper"
describe Chat::ChannelSerializer do describe Chat::ChannelSerializer do
subject(:serializer) { described_class.new(chat_channel, scope: guardian, root: nil) }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
fab!(:admin) { Fabricate(:admin) } fab!(:admin) { Fabricate(:admin) }
fab!(:chat_channel) { Fabricate(:chat_channel) } fab!(:chat_channel) { Fabricate(:chat_channel) }
let(:guardian_user) { user } let(:guardian_user) { user }
let(:guardian) { Guardian.new(guardian_user) } let(:guardian) { Guardian.new(guardian_user) }
subject { described_class.new(chat_channel, scope: guardian, root: nil) }
describe "archive status" do describe "archive status" do
context "when user is not staff" do context "when user is not staff" do
let(:guardian_user) { user } let(:guardian_user) { user }
it "does not return any sort of archive status" do it "does not return any sort of archive status" do
expect(subject.as_json.key?(:archive_completed)).to eq(false) expect(serializer.as_json.key?(:archive_completed)).to eq(false)
end end
it "includes allow_channel_wide_mentions" do it "includes allow_channel_wide_mentions" do
expect(subject.as_json.key?(:allow_channel_wide_mentions)).to eq(true) expect(serializer.as_json.key?(:allow_channel_wide_mentions)).to eq(true)
end end
end end
@ -27,10 +29,10 @@ describe Chat::ChannelSerializer do
let(:guardian_user) { admin } let(:guardian_user) { admin }
it "includes the archive status if the channel is archived and the archive record exists" do it "includes the archive status if the channel is archived and the archive record exists" do
expect(subject.as_json.key?(:archive_completed)).to eq(false) expect(serializer.as_json.key?(:archive_completed)).to eq(false)
chat_channel.update!(status: Chat::Channel.statuses[:archived]) chat_channel.update!(status: Chat::Channel.statuses[:archived])
expect(subject.as_json.key?(:archive_completed)).to eq(false) expect(serializer.as_json.key?(:archive_completed)).to eq(false)
Chat::ChannelArchive.create!( Chat::ChannelArchive.create!(
chat_channel: chat_channel, chat_channel: chat_channel,
@ -39,11 +41,11 @@ describe Chat::ChannelSerializer do
total_messages: 10, total_messages: 10,
) )
chat_channel.reload chat_channel.reload
expect(subject.as_json.key?(:archive_completed)).to eq(true) expect(serializer.as_json.key?(:archive_completed)).to eq(true)
end end
it "includes allow_channel_wide_mentions" do it "includes allow_channel_wide_mentions" do
expect(subject.as_json.key?(:allow_channel_wide_mentions)).to eq(true) expect(serializer.as_json.key?(:allow_channel_wide_mentions)).to eq(true)
end end
end end
end end
@ -63,7 +65,7 @@ describe Chat::ChannelSerializer do
MessageBus.expects(:last_id).with( MessageBus.expects(:last_id).with(
Chat::Publisher.kick_users_message_bus_channel(chat_channel.id), Chat::Publisher.kick_users_message_bus_channel(chat_channel.id),
) )
expect(subject.as_json.dig(:meta, :message_bus_last_ids).keys).to eq( expect(serializer.as_json.dig(:meta, :message_bus_last_ids).keys).to eq(
%i[channel_message_bus_last_id new_messages new_mentions kick], %i[channel_message_bus_last_id new_messages new_mentions kick],
) )
end end
@ -73,7 +75,7 @@ describe Chat::ChannelSerializer do
MessageBus.expects(:last_id).with( MessageBus.expects(:last_id).with(
Chat::Publisher.kick_users_message_bus_channel(chat_channel.id), Chat::Publisher.kick_users_message_bus_channel(chat_channel.id),
) )
expect(subject.as_json[:meta][:message_bus_last_ids].key?(:kick)).to eq(true) expect(serializer.as_json[:meta][:message_bus_last_ids].key?(:kick)).to eq(true)
end end
it "does not call MessageBus for last_id if all the last IDs are already passed in" do it "does not call MessageBus for last_id if all the last IDs are already passed in" do
@ -101,7 +103,7 @@ describe Chat::ChannelSerializer do
MessageBus.expects(:last_id).with( MessageBus.expects(:last_id).with(
Chat::Publisher.new_mentions_message_bus_channel(chat_channel.id), Chat::Publisher.new_mentions_message_bus_channel(chat_channel.id),
) )
expect(subject.as_json.dig(:meta, :message_bus_last_ids).keys).to eq( expect(serializer.as_json.dig(:meta, :message_bus_last_ids).keys).to eq(
%i[channel_message_bus_last_id new_messages new_mentions], %i[channel_message_bus_last_id new_messages new_mentions],
) )
end end
@ -109,7 +111,7 @@ describe Chat::ChannelSerializer do
it "does not get the kick_message_bus_last_id" do it "does not get the kick_message_bus_last_id" do
MessageBus.expects(:last_id).at_least_once MessageBus.expects(:last_id).at_least_once
MessageBus.expects(:last_id).never MessageBus.expects(:last_id).never
expect(subject.as_json[:meta][:message_bus_last_ids].key?(:kick)).to eq(false) expect(serializer.as_json[:meta][:message_bus_last_ids].key?(:kick)).to eq(false)
end end
end end
end end

View File

@ -3,13 +3,14 @@
require "rails_helper" require "rails_helper"
describe Chat::MessageSerializer do describe Chat::MessageSerializer do
subject(:serializer) { described_class.new(message_1, scope: guardian, root: nil) }
fab!(:chat_channel) { Fabricate(:category_channel) } fab!(:chat_channel) { Fabricate(:category_channel) }
fab!(:message_poster) { Fabricate(:user) } fab!(:message_poster) { Fabricate(:user) }
fab!(:message_1) { Fabricate(:chat_message, user: message_poster, chat_channel: chat_channel) } fab!(:message_1) { Fabricate(:chat_message, user: message_poster, chat_channel: chat_channel) }
fab!(:guardian_user) { Fabricate(:user) } fab!(:guardian_user) { Fabricate(:user) }
let(:guardian) { Guardian.new(guardian_user) }
subject { described_class.new(message_1, scope: guardian, root: nil) } let(:guardian) { Guardian.new(guardian_user) }
describe "#reactions" do describe "#reactions" do
fab!(:custom_emoji) { CustomEmoji.create!(name: "trout", upload: Fabricate(:upload)) } fab!(:custom_emoji) { CustomEmoji.create!(name: "trout", upload: Fabricate(:upload)) }
@ -21,13 +22,13 @@ describe Chat::MessageSerializer do
it "doesnt return the reaction" do it "doesnt return the reaction" do
Emoji.clear_cache Emoji.clear_cache
trout_reaction = subject.as_json[:reactions].find { |r| r[:emoji] == "trout" } trout_reaction = serializer.as_json[:reactions].find { |r| r[:emoji] == "trout" }
expect(trout_reaction).to be_present expect(trout_reaction).to be_present
custom_emoji.destroy! custom_emoji.destroy!
Emoji.clear_cache Emoji.clear_cache
trout_reaction = subject.as_json[:reactions].find { |r| r[:emoji] == "trout" } trout_reaction = serializer.as_json[:reactions].find { |r| r[:emoji] == "trout" }
expect(trout_reaction).to_not be_present expect(trout_reaction).to_not be_present
end end
end end
@ -49,7 +50,7 @@ describe Chat::MessageSerializer do
message_1.user.destroy! message_1.user.destroy!
message_1.reload message_1.reload
expect(subject.as_json[:user][:username]).to eq(I18n.t("chat.deleted_chat_username")) expect(serializer.as_json[:user][:username]).to eq(I18n.t("chat.deleted_chat_username"))
end end
end end
end end
@ -60,14 +61,14 @@ describe Chat::MessageSerializer do
message_1.user.destroy! message_1.user.destroy!
message_1.reload message_1.reload
expect(subject.as_json[:deleted_at]).to(be_within(1.second).of(Time.zone.now)) expect(serializer.as_json[:deleted_at]).to(be_within(1.second).of(Time.zone.now))
end end
it "is marked as deleted by system user" do it "is marked as deleted by system user" do
message_1.user.destroy! message_1.user.destroy!
message_1.reload message_1.reload
expect(subject.as_json[:deleted_by_id]).to eq(Discourse.system_user.id) expect(serializer.as_json[:deleted_by_id]).to eq(Discourse.system_user.id)
end end
end end
end end

View File

@ -3,7 +3,7 @@
require "rails_helper" require "rails_helper"
RSpec.describe Chat::MessageUserSerializer do RSpec.describe Chat::MessageUserSerializer do
subject do subject(:serializer) do
user = Fabricate(:user, **params) user = Fabricate(:user, **params)
guardian = Guardian.new(user) guardian = Guardian.new(user)
described_class.new(user, scope: guardian, root: nil).as_json described_class.new(user, scope: guardian, root: nil).as_json
@ -15,11 +15,11 @@ RSpec.describe Chat::MessageUserSerializer do
context "with default user" do context "with default user" do
it "displays user as regular" do it "displays user as regular" do
expect(subject[:new_user]).to eq(false) expect(serializer[:new_user]).to eq(false)
expect(subject[:staff]).to eq(false) expect(serializer[:staff]).to eq(false)
expect(subject[:admin]).to eq(false) expect(serializer[:admin]).to eq(false)
expect(subject[:moderator]).to eq(false) expect(serializer[:moderator]).to eq(false)
expect(subject[:primary_group_name]).to be_blank expect(serializer[:primary_group_name]).to be_blank
end end
end end
@ -27,7 +27,7 @@ RSpec.describe Chat::MessageUserSerializer do
before { params[:trust_level] = TrustLevel[0] } before { params[:trust_level] = TrustLevel[0] }
it "displays user as new" do it "displays user as new" do
expect(subject[:new_user]).to eq(true) expect(serializer[:new_user]).to eq(true)
end end
end end
@ -35,7 +35,7 @@ RSpec.describe Chat::MessageUserSerializer do
before { params[:admin] = true } before { params[:admin] = true }
it "displays user as staff" do it "displays user as staff" do
expect(subject[:staff]).to eq(true) expect(serializer[:staff]).to eq(true)
end end
end end
@ -43,7 +43,7 @@ RSpec.describe Chat::MessageUserSerializer do
before { params[:admin] = true } before { params[:admin] = true }
it "displays user as admin" do it "displays user as admin" do
expect(subject[:admin]).to eq(true) expect(serializer[:admin]).to eq(true)
end end
end end
@ -51,7 +51,7 @@ RSpec.describe Chat::MessageUserSerializer do
before { params[:moderator] = true } before { params[:moderator] = true }
it "displays user as moderator" do it "displays user as moderator" do
expect(subject[:moderator]).to eq(true) expect(serializer[:moderator]).to eq(true)
end end
end end
@ -61,7 +61,7 @@ RSpec.describe Chat::MessageUserSerializer do
before { params[:primary_group_id] = group.id } before { params[:primary_group_id] = group.id }
it "displays user as moderator" do it "displays user as moderator" do
expect(subject[:primary_group_name]).to eq(group.name) expect(serializer[:primary_group_name]).to eq(group.name)
end end
end end
end end

View File

@ -11,6 +11,8 @@ RSpec.describe Chat::ChannelViewBuilder do
end end
describe ".call" do describe ".call" do
subject(:result) { described_class.call(params) }
fab!(:current_user) { Fabricate(:user) } fab!(:current_user) { Fabricate(:user) }
fab!(:channel) { Fabricate(:category_channel) } fab!(:channel) { Fabricate(:category_channel) }
@ -35,14 +37,12 @@ RSpec.describe Chat::ChannelViewBuilder do
} }
end end
subject(:result) { described_class.call(params) }
it "threads_enabled is false by default" do it "threads_enabled is false by default" do
expect(subject.threads_enabled).to eq(false) expect(result.threads_enabled).to eq(false)
end end
it "include_thread_messages is true by default" do it "include_thread_messages is true by default" do
expect(subject.include_thread_messages).to eq(true) expect(result.include_thread_messages).to eq(true)
end end
it "queries messages" do it "queries messages" do
@ -59,7 +59,7 @@ RSpec.describe Chat::ChannelViewBuilder do
target_date: target_date, target_date: target_date,
) )
.returns({ messages: [] }) .returns({ messages: [] })
subject result
end end
it "returns channel messages and thread replies" do it "returns channel messages and thread replies" do
@ -71,23 +71,23 @@ RSpec.describe Chat::ChannelViewBuilder do
chat_channel: channel, chat_channel: channel,
thread: Fabricate(:chat_thread, channel: channel), thread: Fabricate(:chat_thread, channel: channel),
) )
expect(subject.view.chat_messages).to eq( expect(result.view.chat_messages).to eq(
[message_1, message_2, message_3.thread.original_message, message_3], [message_1, message_2, message_3.thread.original_message, message_3],
) )
end end
it "does not query thread tracking overview or state by default" do it "does not query thread tracking overview or state by default" do
Chat::TrackingStateReportQuery.expects(:call).never Chat::TrackingStateReportQuery.expects(:call).never
subject result
end end
it "does not query threads by default" do it "does not query threads by default" do
Chat::Thread.expects(:where).never Chat::Thread.expects(:where).never
subject result
end end
it "returns a Chat::View" do it "returns a Chat::View" do
expect(subject.view).to be_a(Chat::View) expect(result.view).to be_a(Chat::View)
end end
context "when page_size is null" do context "when page_size is null" do
@ -109,11 +109,11 @@ RSpec.describe Chat::ChannelViewBuilder do
end end
it "threads_enabled is true" do it "threads_enabled is true" do
expect(subject.threads_enabled).to eq(true) expect(result.threads_enabled).to eq(true)
end end
it "include_thread_messages is false" do it "include_thread_messages is false" do
expect(subject.include_thread_messages).to eq(false) expect(result.include_thread_messages).to eq(false)
end end
it "returns channel messages but not thread replies" do it "returns channel messages but not thread replies" do
@ -125,7 +125,7 @@ RSpec.describe Chat::ChannelViewBuilder do
chat_channel: channel, chat_channel: channel,
thread: Fabricate(:chat_thread, channel: channel), thread: Fabricate(:chat_thread, channel: channel),
) )
expect(subject.view.chat_messages).to eq( expect(result.view.chat_messages).to eq(
[message_1, message_2, message_3.thread.original_message], [message_1, message_2, message_3.thread.original_message],
) )
end end
@ -137,7 +137,7 @@ RSpec.describe Chat::ChannelViewBuilder do
chat_channel: channel, chat_channel: channel,
thread: Fabricate(:chat_thread, channel: channel), thread: Fabricate(:chat_thread, channel: channel),
) )
expect(subject.view.threads).to eq([message_1.thread]) expect(result.view.threads).to eq([message_1.thread])
end end
it "fetches thread memberships for the current user for fetched threads" do it "fetches thread memberships for the current user for fetched threads" do
@ -148,7 +148,7 @@ RSpec.describe Chat::ChannelViewBuilder do
thread: Fabricate(:chat_thread, channel: channel), thread: Fabricate(:chat_thread, channel: channel),
) )
message_1.thread.add(current_user) message_1.thread.add(current_user)
expect(subject.view.thread_memberships).to eq( expect(result.view.thread_memberships).to eq(
[message_1.thread.membership_for(current_user)], [message_1.thread.membership_for(current_user)],
) )
end end
@ -171,21 +171,21 @@ RSpec.describe Chat::ChannelViewBuilder do
.with(guardian: guardian, thread_ids: [thread.id], include_threads: true) .with(guardian: guardian, thread_ids: [thread.id], include_threads: true)
.returns(Chat::TrackingStateReport.new) .returns(Chat::TrackingStateReport.new)
.once .once
subject result
end end
it "fetches an overview of threads with unread messages in the channel" do it "fetches an overview of threads with unread messages in the channel" do
thread = Fabricate(:chat_thread, channel: channel) thread = Fabricate(:chat_thread, channel: channel)
thread.add(current_user) thread.add(current_user)
message_1 = Fabricate(:chat_message, chat_channel: channel, thread: thread) message_1 = Fabricate(:chat_message, chat_channel: channel, thread: thread)
expect(subject.view.unread_thread_ids).to eq([message_1.thread.id]) expect(result.view.unread_thread_ids).to eq([message_1.thread.id])
end end
it "fetches the tracking state of threads in the channel" do it "fetches the tracking state of threads in the channel" do
thread = Fabricate(:chat_thread, channel: channel) thread = Fabricate(:chat_thread, channel: channel)
thread.add(current_user) thread.add(current_user)
Fabricate(:chat_message, chat_channel: channel, thread: thread) Fabricate(:chat_message, chat_channel: channel, thread: thread)
expect(subject.view.tracking.thread_tracking).to eq( expect(result.view.tracking.thread_tracking).to eq(
{ thread.id => { channel_id: channel.id, unread_count: 1, mention_count: 0 } }, { thread.id => { channel_id: channel.id, unread_count: 1, mention_count: 0 } },
) )
end end
@ -194,7 +194,7 @@ RSpec.describe Chat::ChannelViewBuilder do
let(:thread_id) { Fabricate(:chat_thread, channel: channel).id } let(:thread_id) { Fabricate(:chat_thread, channel: channel).id }
it "include_thread_messages is true" do it "include_thread_messages is true" do
expect(subject.include_thread_messages).to eq(true) expect(result.include_thread_messages).to eq(true)
end end
end end
end end
@ -233,7 +233,7 @@ RSpec.describe Chat::ChannelViewBuilder do
context "if the user is not a member of the channel" do context "if the user is not a member of the channel" do
it "does not error and still returns messages" do it "does not error and still returns messages" do
expect(subject.view.chat_messages).to eq([past_message_2, past_message_1, message]) expect(result.view.chat_messages).to eq([past_message_2, past_message_1, message])
end end
end end
@ -246,7 +246,7 @@ RSpec.describe Chat::ChannelViewBuilder do
before { membership.update!(last_read_message_id: past_message_1.id) } before { membership.update!(last_read_message_id: past_message_1.id) }
it "uses the last_read_message_id of the user's membership as the target_message_id" do it "uses the last_read_message_id of the user's membership as the target_message_id" do
expect(subject.view.chat_messages).to eq([past_message_2, past_message_1, message]) expect(result.view.chat_messages).to eq([past_message_2, past_message_1, message])
end end
end end
@ -254,7 +254,7 @@ RSpec.describe Chat::ChannelViewBuilder do
before { membership.update!(last_read_message_id: nil) } before { membership.update!(last_read_message_id: nil) }
it "does not error and still returns messages" do it "does not error and still returns messages" do
expect(subject.view.chat_messages).to eq([past_message_2, past_message_1, message]) expect(result.view.chat_messages).to eq([past_message_2, past_message_1, message])
end end
context "if page_size is nil" do context "if page_size is nil" do
@ -266,7 +266,7 @@ RSpec.describe Chat::ChannelViewBuilder do
.with(has_entries(page_size: Chat::MessagesQuery::MAX_PAGE_SIZE)) .with(has_entries(page_size: Chat::MessagesQuery::MAX_PAGE_SIZE))
.once .once
.returns({ messages: [] }) .returns({ messages: [] })
subject result
end end
end end
end end
@ -288,7 +288,7 @@ RSpec.describe Chat::ChannelViewBuilder do
let(:target_message_id) { message.id } let(:target_message_id) { message.id }
it "includes the target message as well as past and future messages" do it "includes the target message as well as past and future messages" do
expect(subject.view.chat_messages).to eq([past_message, message, future_message]) expect(result.view.chat_messages).to eq([past_message, message, future_message])
end end
context "when page_size is null" do context "when page_size is null" do
@ -303,7 +303,7 @@ RSpec.describe Chat::ChannelViewBuilder do
before { message.update!(thread: thread) } before { message.update!(thread: thread) }
it "includes it by default" do it "includes it by default" do
expect(subject.view.chat_messages).to eq( expect(result.view.chat_messages).to eq(
[past_message, message, thread.original_message, future_message], [past_message, message, thread.original_message, future_message],
) )
end end
@ -315,7 +315,7 @@ RSpec.describe Chat::ChannelViewBuilder do
end end
it "does not include the target message" do it "does not include the target message" do
expect(subject.view.chat_messages).to eq( expect(result.view.chat_messages).to eq(
[past_message, thread.original_message, future_message], [past_message, thread.original_message, future_message],
) )
end end
@ -356,7 +356,7 @@ RSpec.describe Chat::ChannelViewBuilder do
let(:target_date) { 2.days.ago } let(:target_date) { 2.days.ago }
it "includes past and future messages" do it "includes past and future messages" do
expect(subject.view.chat_messages).to eq([past_message, future_message]) expect(result.view.chat_messages).to eq([past_message, future_message])
end end
end end
end end

View File

@ -3,8 +3,9 @@
require "rails_helper" require "rails_helper"
RSpec.describe ::DiscoursePoll::PollsValidator do RSpec.describe ::DiscoursePoll::PollsValidator do
subject(:validator) { described_class.new(post) }
let(:post) { Fabricate(:post) } let(:post) { Fabricate(:post) }
subject { described_class.new(post) }
describe "#validate_polls" do describe "#validate_polls" do
it "ensures that polls have valid arguments" do it "ensures that polls have valid arguments" do

View File

@ -23,11 +23,12 @@ RSpec.describe EmailStyle do
end end
context "with invite" do context "with invite" do
fab!(:invite) { Fabricate(:invite) }
let(:invite_mail) { InviteMailer.send_invite(invite) }
subject(:mail_html) { Email::Renderer.new(invite_mail).html } subject(:mail_html) { Email::Renderer.new(invite_mail).html }
fab!(:invite) { Fabricate(:invite) }
let(:invite_mail) { InviteMailer.send_invite(invite) }
it "applies customizations" do it "applies customizations" do
expect(mail_html.scan('<h1 style="color: red;">FOR YOU</h1>').count).to eq(1) expect(mail_html.scan('<h1 style="color: red;">FOR YOU</h1>').count).to eq(1)
expect(mail_html).to match("#{Discourse.base_url}/invites/#{invite.invite_key}") expect(mail_html).to match("#{Discourse.base_url}/invites/#{invite.invite_key}")
@ -48,6 +49,8 @@ RSpec.describe EmailStyle do
end end
context "when user_replied" do context "when user_replied" do
subject(:mail_html) { Email::Renderer.new(mail).html }
let(:response_by_user) { Fabricate(:user, name: "John Doe") } let(:response_by_user) { Fabricate(:user, name: "John Doe") }
let(:category) { Fabricate(:category, name: "India") } let(:category) { Fabricate(:category, name: "India") }
let(:topic) { Fabricate(:topic, category: category, title: "Super cool topic") } let(:topic) { Fabricate(:topic, category: category, title: "Super cool topic") }
@ -65,8 +68,6 @@ RSpec.describe EmailStyle do
) )
end end
subject(:mail_html) { Email::Renderer.new(mail).html }
it "customizations are applied to html part of emails" do it "customizations are applied to html part of emails" do
SiteSetting.default_email_in_reply_to = true SiteSetting.default_email_in_reply_to = true
@ -80,9 +81,10 @@ RSpec.describe EmailStyle do
end end
context "with signup" do context "with signup" do
let(:signup_mail) { UserNotifications.signup(Fabricate(:user)) }
subject(:mail_html) { Email::Renderer.new(signup_mail).html } subject(:mail_html) { Email::Renderer.new(signup_mail).html }
let(:signup_mail) { UserNotifications.signup(Fabricate(:user)) }
it "customizations are applied to html part of emails" do it "customizations are applied to html part of emails" do
expect(mail_html.scan('<h1 style="color: red;">FOR YOU</h1>').count).to eq(1) expect(mail_html.scan('<h1 style="color: red;">FOR YOU</h1>').count).to eq(1)
expect(mail_html).to include("activate-account") expect(mail_html).to include("activate-account")
@ -124,11 +126,13 @@ RSpec.describe EmailStyle do
end end
context "with digest" do context "with digest" do
subject(:mail_html) { Email::Renderer.new(summary_email).html }
fab!(:popular_topic) do fab!(:popular_topic) do
Fabricate(:topic, user: Fabricate(:coding_horror), created_at: 1.hour.ago) Fabricate(:topic, user: Fabricate(:coding_horror), created_at: 1.hour.ago)
end end
let(:summary_email) { UserNotifications.digest(Fabricate(:user)) } let(:summary_email) { UserNotifications.digest(Fabricate(:user)) }
subject(:mail_html) { Email::Renderer.new(summary_email).html }
it "customizations are applied to html part of emails" do it "customizations are applied to html part of emails" do
expect(mail_html.scan('<h1 style="color: red;">FOR YOU</h1>').count).to eq(1) expect(mail_html.scan('<h1 style="color: red;">FOR YOU</h1>').count).to eq(1)

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::AutoQueueHandler do RSpec.describe Jobs::AutoQueueHandler do
subject { Jobs::AutoQueueHandler.new.execute({}) } subject(:job) { Jobs::AutoQueueHandler.new.execute({}) }
describe "old flagged post" do describe "old flagged post" do
fab!(:spam_result) do fab!(:spam_result) do
@ -23,7 +23,7 @@ RSpec.describe Jobs::AutoQueueHandler do
it "defers the old flag if auto_handle_queued_age is 60" do it "defers the old flag if auto_handle_queued_age is 60" do
SiteSetting.auto_handle_queued_age = 60 SiteSetting.auto_handle_queued_age = 60
subject job
expect(not_old.reload).to be_pending expect(not_old.reload).to be_pending
expect(old.reload).not_to be_pending expect(old.reload).not_to be_pending
expect(post_action.related_post.topic.posts_count).to eq(1) expect(post_action.related_post.topic.posts_count).to eq(1)
@ -31,7 +31,7 @@ RSpec.describe Jobs::AutoQueueHandler do
it "doesn't defer the old flag if auto_handle_queued_age is 0" do it "doesn't defer the old flag if auto_handle_queued_age is 0" do
SiteSetting.auto_handle_queued_age = 0 SiteSetting.auto_handle_queued_age = 0
subject job
expect(not_old.reload).to be_pending expect(not_old.reload).to be_pending
expect(old.reload).to be_pending expect(old.reload).to be_pending
end end
@ -45,7 +45,7 @@ RSpec.describe Jobs::AutoQueueHandler do
it "rejects the post when auto_handle_queued_age is 60" do it "rejects the post when auto_handle_queued_age is 60" do
SiteSetting.auto_handle_queued_age = 60 SiteSetting.auto_handle_queued_age = 60
subject job
expect(new_post.reload.pending?).to eq(true) expect(new_post.reload.pending?).to eq(true)
expect(old_post.reload.rejected?).to eq(true) expect(old_post.reload.rejected?).to eq(true)
expect(new_user.reload.pending?).to eq(true) expect(new_user.reload.pending?).to eq(true)
@ -54,7 +54,7 @@ RSpec.describe Jobs::AutoQueueHandler do
it "leaves reviewables as pending auto_handle_queued_age is 0" do it "leaves reviewables as pending auto_handle_queued_age is 0" do
SiteSetting.auto_handle_queued_age = 0 SiteSetting.auto_handle_queued_age = 0
subject job
expect(new_post.reload.pending?).to eq(true) expect(new_post.reload.pending?).to eq(true)
expect(new_user.reload.pending?).to eq(true) expect(new_user.reload.pending?).to eq(true)
expect(old_post.reload.pending?).to eq(true) expect(old_post.reload.pending?).to eq(true)

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::BookmarkReminderNotifications do RSpec.describe Jobs::BookmarkReminderNotifications do
subject { described_class.new } subject(:job) { described_class.new }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
let(:five_minutes_ago) { Time.zone.now - 5.minutes } let(:five_minutes_ago) { Time.zone.now - 5.minutes }
@ -19,7 +19,7 @@ RSpec.describe Jobs::BookmarkReminderNotifications do
end end
it "sends every reminder and sets the reminder_last_sent_at" do it "sends every reminder and sets the reminder_last_sent_at" do
subject.execute job.execute
bookmark1.reload bookmark1.reload
bookmark2.reload bookmark2.reload
bookmark3.reload bookmark3.reload
@ -31,7 +31,7 @@ RSpec.describe Jobs::BookmarkReminderNotifications do
it "will not send a reminder for a bookmark in the future" do it "will not send a reminder for a bookmark in the future" do
freeze_time freeze_time
bookmark4 = Fabricate(:bookmark, reminder_at: Time.zone.now + 1.day) bookmark4 = Fabricate(:bookmark, reminder_at: Time.zone.now + 1.day)
expect { subject.execute }.to change { Notification.where(user: user).count }.by(3) expect { job.execute }.to change { Notification.where(user: user).count }.by(3)
expect(bookmark1.reload.reminder_last_sent_at).to eq_time(Time.zone.now) expect(bookmark1.reload.reminder_last_sent_at).to eq_time(Time.zone.now)
expect(bookmark2.reload.reminder_last_sent_at).to eq_time(Time.zone.now) expect(bookmark2.reload.reminder_last_sent_at).to eq_time(Time.zone.now)
expect(bookmark3.reload.reminder_last_sent_at).to eq_time(Time.zone.now) expect(bookmark3.reload.reminder_last_sent_at).to eq_time(Time.zone.now)
@ -44,7 +44,7 @@ RSpec.describe Jobs::BookmarkReminderNotifications do
other_bookmark = Fabricate(:bookmark, user: bookmark1.user) other_bookmark = Fabricate(:bookmark, user: bookmark1.user)
other_bookmark.update_column(:reminder_at, five_minutes_ago) other_bookmark.update_column(:reminder_at, five_minutes_ago)
SiteSetting.max_bookmarks_per_user = 2 SiteSetting.max_bookmarks_per_user = 2
expect { subject.execute }.not_to raise_error expect { job.execute }.not_to raise_error
end end
end end
@ -52,7 +52,7 @@ RSpec.describe Jobs::BookmarkReminderNotifications do
it "does not send them in the current run, but will send them in the next" do it "does not send them in the current run, but will send them in the next" do
begin begin
Jobs::BookmarkReminderNotifications.max_reminder_notifications_per_run = 2 Jobs::BookmarkReminderNotifications.max_reminder_notifications_per_run = 2
subject.execute job.execute
expect(bookmark1.reload.reminder_last_sent_at).not_to eq(nil) expect(bookmark1.reload.reminder_last_sent_at).not_to eq(nil)
expect(bookmark2.reload.reminder_last_sent_at).not_to eq(nil) expect(bookmark2.reload.reminder_last_sent_at).not_to eq(nil)
expect(bookmark3.reload.reminder_last_sent_at).to eq(nil) expect(bookmark3.reload.reminder_last_sent_at).to eq(nil)
@ -64,7 +64,7 @@ RSpec.describe Jobs::BookmarkReminderNotifications do
bookmark1.bookmarkable.topic.destroy bookmark1.bookmarkable.topic.destroy
bookmark2.bookmarkable.topic.destroy bookmark2.bookmarkable.topic.destroy
bookmark3.bookmarkable.topic.destroy bookmark3.bookmarkable.topic.destroy
expect { subject.execute }.not_to change { expect { job.execute }.not_to change {
Notification.where(notification_type: Notification.types[:bookmark_reminder]).count Notification.where(notification_type: Notification.types[:bookmark_reminder]).count
} }
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::CleanUpAssociatedAccounts do RSpec.describe Jobs::CleanUpAssociatedAccounts do
subject { Jobs::CleanUpAssociatedAccounts.new.execute({}) } subject(:job) { Jobs::CleanUpAssociatedAccounts.new.execute({}) }
it "deletes the correct records" do it "deletes the correct records" do
freeze_time freeze_time
@ -26,7 +26,7 @@ RSpec.describe Jobs::CleanUpAssociatedAccounts do
updated_at: 12.hours.ago, updated_at: 12.hours.ago,
) )
expect { subject }.to change { UserAssociatedAccount.count }.by(-1) expect { job }.to change { UserAssociatedAccount.count }.by(-1)
expect(UserAssociatedAccount.all).to contain_exactly(today, connected) expect(UserAssociatedAccount.all).to contain_exactly(today, connected)
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::CleanUpCrawlerStats do RSpec.describe Jobs::CleanUpCrawlerStats do
subject { Jobs::CleanUpCrawlerStats.new.execute({}) } subject(:job) { Jobs::CleanUpCrawlerStats.new.execute({}) }
it "deletes records older than 30 days old" do it "deletes records older than 30 days old" do
freeze_time freeze_time
@ -10,7 +10,7 @@ RSpec.describe Jobs::CleanUpCrawlerStats do
yesterday = Fabricate(:web_crawler_request, date: 1.day.ago.to_date) yesterday = Fabricate(:web_crawler_request, date: 1.day.ago.to_date)
too_old = Fabricate(:web_crawler_request, date: 31.days.ago.to_date) too_old = Fabricate(:web_crawler_request, date: 31.days.ago.to_date)
expect { subject }.to change { WebCrawlerRequest.count }.by(-1) expect { job }.to change { WebCrawlerRequest.count }.by(-1)
expect(WebCrawlerRequest.where(id: too_old.id)).to_not exist expect(WebCrawlerRequest.where(id: too_old.id)).to_not exist
end end
@ -25,7 +25,7 @@ RSpec.describe Jobs::CleanUpCrawlerStats do
req2 = Fabricate(:web_crawler_request, date: 1.day.ago.to_date, count: 50) req2 = Fabricate(:web_crawler_request, date: 1.day.ago.to_date, count: 50)
req5 = Fabricate(:web_crawler_request, date: 1.day.ago.to_date, count: 1) req5 = Fabricate(:web_crawler_request, date: 1.day.ago.to_date, count: 1)
expect { subject }.to change { WebCrawlerRequest.count }.by(-2) expect { job }.to change { WebCrawlerRequest.count }.by(-2)
expect(WebCrawlerRequest.all).to contain_exactly(req1, req2, req3) expect(WebCrawlerRequest.all).to contain_exactly(req1, req2, req3)
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::CreateRecentPostSearchIndexes do RSpec.describe Jobs::CreateRecentPostSearchIndexes do
subject { described_class.new } subject(:job) { described_class.new }
fab!(:post) { with_search_indexer_enabled { Fabricate(:post) } } fab!(:post) { with_search_indexer_enabled { Fabricate(:post) } }
fab!(:post_2) { with_search_indexer_enabled { Fabricate(:post) } } fab!(:post_2) { with_search_indexer_enabled { Fabricate(:post) } }
@ -13,7 +13,7 @@ RSpec.describe Jobs::CreateRecentPostSearchIndexes do
SiteSetting.search_recent_posts_size = 1 SiteSetting.search_recent_posts_size = 1
SiteSetting.search_enable_recent_regular_posts_offset_size = 3 SiteSetting.search_enable_recent_regular_posts_offset_size = 3
expect do subject.execute({}) end.to_not change { expect { job.execute({}) }.to_not change {
SiteSetting.search_recent_regular_posts_offset_post_id SiteSetting.search_recent_regular_posts_offset_post_id
} }
end end
@ -22,7 +22,7 @@ RSpec.describe Jobs::CreateRecentPostSearchIndexes do
SiteSetting.search_recent_posts_size = 1 SiteSetting.search_recent_posts_size = 1
SiteSetting.search_enable_recent_regular_posts_offset_size = 1 SiteSetting.search_enable_recent_regular_posts_offset_size = 1
subject.execute({}) job.execute({})
expect(SiteSetting.search_recent_regular_posts_offset_post_id).to eq(post_2.id) expect(SiteSetting.search_recent_regular_posts_offset_post_id).to eq(post_2.id)

View File

@ -3,25 +3,27 @@
require "excon" require "excon"
RSpec.describe Jobs::EmitWebHookEvent do RSpec.describe Jobs::EmitWebHookEvent do
subject(:job) { described_class.new }
fab!(:post_hook) { Fabricate(:web_hook) } fab!(:post_hook) { Fabricate(:web_hook) }
fab!(:inactive_hook) { Fabricate(:inactive_web_hook) } fab!(:inactive_hook) { Fabricate(:inactive_web_hook) }
fab!(:post) { Fabricate(:post) } fab!(:post) { Fabricate(:post) }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
it "raises an error when there is no web hook record" do it "raises an error when there is no web hook record" do
expect do subject.execute(event_type: "post", payload: {}) end.to raise_error( expect { job.execute(event_type: "post", payload: {}) }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
) )
end end
it "raises an error when there is no event type" do it "raises an error when there is no event type" do
expect do subject.execute(web_hook_id: post_hook.id, payload: {}) end.to raise_error( expect { job.execute(web_hook_id: post_hook.id, payload: {}) }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
) )
end end
it "raises an error when there is no payload" do it "raises an error when there is no payload" do
expect do subject.execute(web_hook_id: post_hook.id, event_type: "post") end.to raise_error( expect { job.execute(web_hook_id: post_hook.id, event_type: "post") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
) )
end end
@ -29,7 +31,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
it "should not destroy webhook event in case of error" do it "should not destroy webhook event in case of error" do
stub_request(:post, post_hook.payload_url).to_return(status: 500) stub_request(:post, post_hook.payload_url).to_return(status: 500)
subject.execute( job.execute(
web_hook_id: post_hook.id, web_hook_id: post_hook.id,
payload: { id: post.id }.to_json, payload: { id: post.id }.to_json,
event_type: WebHookEventType::POST, event_type: WebHookEventType::POST,
@ -53,7 +55,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
it "disables the webhook" do it "disables the webhook" do
expect do expect do
subject.execute( job.execute(
web_hook_id: post_hook.id, web_hook_id: post_hook.id,
event_type: described_class::PING_EVENT, event_type: described_class::PING_EVENT,
retry_count: described_class::MAX_RETRY_COUNT, retry_count: described_class::MAX_RETRY_COUNT,
@ -62,7 +64,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
end end
it "logs webhook deactivation reason" do it "logs webhook deactivation reason" do
subject.execute( job.execute(
web_hook_id: post_hook.id, web_hook_id: post_hook.id,
event_type: described_class::PING_EVENT, event_type: described_class::PING_EVENT,
retry_count: described_class::MAX_RETRY_COUNT, retry_count: described_class::MAX_RETRY_COUNT,
@ -86,7 +88,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
it "retry if site setting is enabled" do it "retry if site setting is enabled" do
expect do expect do
subject.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT) job.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT)
end.to change { Jobs::EmitWebHookEvent.jobs.size }.by(1) end.to change { Jobs::EmitWebHookEvent.jobs.size }.by(1)
end end
@ -96,13 +98,13 @@ RSpec.describe Jobs::EmitWebHookEvent do
expect(Jobs::EmitWebHookEvent::MAX_RETRY_COUNT + 1).to eq(5) expect(Jobs::EmitWebHookEvent::MAX_RETRY_COUNT + 1).to eq(5)
expect do expect do
subject.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT) job.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT)
end.to change { WebHookEvent.count }.by(Jobs::EmitWebHookEvent::MAX_RETRY_COUNT + 1) end.to change { WebHookEvent.count }.by(Jobs::EmitWebHookEvent::MAX_RETRY_COUNT + 1)
end end
it "does not retry for more than maximum allowed times" do it "does not retry for more than maximum allowed times" do
expect do expect do
subject.execute( job.execute(
web_hook_id: post_hook.id, web_hook_id: post_hook.id,
event_type: described_class::PING_EVENT, event_type: described_class::PING_EVENT,
retry_count: described_class::MAX_RETRY_COUNT, retry_count: described_class::MAX_RETRY_COUNT,
@ -114,13 +116,13 @@ RSpec.describe Jobs::EmitWebHookEvent do
SiteSetting.retry_web_hook_events = false SiteSetting.retry_web_hook_events = false
expect do expect do
subject.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT) job.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT)
end.not_to change { Jobs::EmitWebHookEvent.jobs.size } end.not_to change { Jobs::EmitWebHookEvent.jobs.size }
end end
it "properly logs error on rescue" do it "properly logs error on rescue" do
stub_request(:post, post_hook.payload_url).to_raise("connection error") stub_request(:post, post_hook.payload_url).to_raise("connection error")
subject.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT) job.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT)
event = WebHookEvent.last event = WebHookEvent.last
expect(event.payload).to eq(MultiJson.dump(ping: "OK")) expect(event.payload).to eq(MultiJson.dump(ping: "OK"))
@ -133,11 +135,11 @@ RSpec.describe Jobs::EmitWebHookEvent do
it "does not raise an error for a ping event without payload" do it "does not raise an error for a ping event without payload" do
stub_request(:post, post_hook.payload_url).to_return(body: "OK", status: 200) stub_request(:post, post_hook.payload_url).to_return(body: "OK", status: 200)
subject.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT) job.execute(web_hook_id: post_hook.id, event_type: described_class::PING_EVENT)
end end
it "doesn't emit when the hook is inactive" do it "doesn't emit when the hook is inactive" do
subject.execute( job.execute(
web_hook_id: inactive_hook.id, web_hook_id: inactive_hook.id,
event_type: "post", event_type: "post",
payload: { test: "some payload" }.to_json, payload: { test: "some payload" }.to_json,
@ -149,7 +151,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
body: "{\"post\":{\"test\":\"some payload\"}}", body: "{\"post\":{\"test\":\"some payload\"}}",
).to_return(body: "OK", status: 200) ).to_return(body: "OK", status: 200)
subject.execute( job.execute(
web_hook_id: post_hook.id, web_hook_id: post_hook.id,
event_type: "post", event_type: "post",
payload: { test: "some payload" }.to_json, payload: { test: "some payload" }.to_json,
@ -158,7 +160,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
it "doesn't emit if the payload URL resolves to a disallowed IP" do it "doesn't emit if the payload URL resolves to a disallowed IP" do
FinalDestination::TestHelper.stub_to_fail do FinalDestination::TestHelper.stub_to_fail do
subject.execute( job.execute(
web_hook_id: post_hook.id, web_hook_id: post_hook.id,
event_type: "post", event_type: "post",
payload: { test: "some payload" }.to_json, payload: { test: "some payload" }.to_json,
@ -179,7 +181,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
fab!(:topic_hook) { Fabricate(:topic_web_hook, categories: [category]) } fab!(:topic_hook) { Fabricate(:topic_web_hook, categories: [category]) }
it "doesn't emit when event is not related with defined categories" do it "doesn't emit when event is not related with defined categories" do
subject.execute( job.execute(
web_hook_id: topic_hook.id, web_hook_id: topic_hook.id,
event_type: "topic", event_type: "topic",
category_id: topic.category.id, category_id: topic.category.id,
@ -192,7 +194,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
body: "{\"topic\":{\"test\":\"some payload\"}}", body: "{\"topic\":{\"test\":\"some payload\"}}",
).to_return(body: "OK", status: 200) ).to_return(body: "OK", status: 200)
subject.execute( job.execute(
web_hook_id: topic_hook.id, web_hook_id: topic_hook.id,
event_type: "topic", event_type: "topic",
category_id: topic_with_category.category.id, category_id: topic_with_category.category.id,
@ -207,7 +209,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
fab!(:topic_hook) { Fabricate(:topic_web_hook, tags: [tag]) } fab!(:topic_hook) { Fabricate(:topic_web_hook, tags: [tag]) }
it "doesn't emit when event is not included any tags" do it "doesn't emit when event is not included any tags" do
subject.execute( job.execute(
web_hook_id: topic_hook.id, web_hook_id: topic_hook.id,
event_type: "topic", event_type: "topic",
payload: { test: "some payload" }.to_json, payload: { test: "some payload" }.to_json,
@ -215,7 +217,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
end end
it "doesn't emit when event is not related with defined tags" do it "doesn't emit when event is not related with defined tags" do
subject.execute( job.execute(
web_hook_id: topic_hook.id, web_hook_id: topic_hook.id,
event_type: "topic", event_type: "topic",
tag_ids: [Fabricate(:tag).id], tag_ids: [Fabricate(:tag).id],
@ -228,7 +230,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
body: "{\"topic\":{\"test\":\"some payload\"}}", body: "{\"topic\":{\"test\":\"some payload\"}}",
).to_return(body: "OK", status: 200) ).to_return(body: "OK", status: 200)
subject.execute( job.execute(
web_hook_id: topic_hook.id, web_hook_id: topic_hook.id,
event_type: "topic", event_type: "topic",
tag_ids: topic.tags.pluck(:id), tag_ids: topic.tags.pluck(:id),
@ -243,7 +245,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
fab!(:like_hook) { Fabricate(:like_web_hook, groups: [group]) } fab!(:like_hook) { Fabricate(:like_web_hook, groups: [group]) }
it "doesn't emit when event is not included any groups" do it "doesn't emit when event is not included any groups" do
subject.execute( job.execute(
web_hook_id: like_hook.id, web_hook_id: like_hook.id,
event_type: "like", event_type: "like",
payload: { test: "some payload" }.to_json, payload: { test: "some payload" }.to_json,
@ -251,7 +253,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
end end
it "doesn't emit when event is not related with defined groups" do it "doesn't emit when event is not related with defined groups" do
subject.execute( job.execute(
web_hook_id: like_hook.id, web_hook_id: like_hook.id,
event_type: "like", event_type: "like",
group_ids: [Fabricate(:group).id], group_ids: [Fabricate(:group).id],
@ -264,7 +266,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
body: "{\"like\":{\"test\":\"some payload\"}}", body: "{\"like\":{\"test\":\"some payload\"}}",
).to_return(body: "OK", status: 200) ).to_return(body: "OK", status: 200)
subject.execute( job.execute(
web_hook_id: like_hook.id, web_hook_id: like_hook.id,
event_type: "like", event_type: "like",
group_ids: user.groups.pluck(:id), group_ids: user.groups.pluck(:id),
@ -281,7 +283,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
web_hook_id = Fabricate("#{topic_event_type.name}_web_hook").id web_hook_id = Fabricate("#{topic_event_type.name}_web_hook").id
expect do expect do
subject.execute( job.execute(
web_hook_id: web_hook_id, web_hook_id: web_hook_id,
event_type: topic_event_type.name, event_type: topic_event_type.name,
payload: { test: "some payload" }.to_json, payload: { test: "some payload" }.to_json,
@ -298,7 +300,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
status: 200, status: 200,
) )
subject.execute( job.execute(
web_hook_id: post_hook.id, web_hook_id: post_hook.id,
event_type: described_class::PING_EVENT, event_type: described_class::PING_EVENT,
event_name: described_class::PING_EVENT, event_name: described_class::PING_EVENT,
@ -324,7 +326,7 @@ RSpec.describe Jobs::EmitWebHookEvent do
it "sets up proper request headers when an error raised" do it "sets up proper request headers when an error raised" do
stub_request(:post, post_hook.payload_url).to_raise("error") stub_request(:post, post_hook.payload_url).to_raise("error")
subject.execute( job.execute(
web_hook_id: post_hook.id, web_hook_id: post_hook.id,
event_type: described_class::PING_EVENT, event_type: described_class::PING_EVENT,
event_name: described_class::PING_EVENT, event_name: described_class::PING_EVENT,

View File

@ -1,10 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::EnqueueSuspectUsers do RSpec.describe Jobs::EnqueueSuspectUsers do
subject(:job) { described_class.new }
before { SiteSetting.approve_suspect_users = true } before { SiteSetting.approve_suspect_users = true }
it "does nothing when there are no suspect users" do it "does nothing when there are no suspect users" do
subject.execute({}) job.execute({})
expect(ReviewableUser.count).to be_zero expect(ReviewableUser.count).to be_zero
end end
@ -13,7 +15,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
let!(:suspect_user) { Fabricate(:active_user, created_at: 1.day.ago) } let!(:suspect_user) { Fabricate(:active_user, created_at: 1.day.ago) }
it "creates a reviewable when there is a suspect user" do it "creates a reviewable when there is a suspect user" do
subject.execute({}) job.execute({})
expect(ReviewableUser.count).to eq(1) expect(ReviewableUser.count).to eq(1)
end end
@ -26,14 +28,14 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
reviewable_by_moderator: true, reviewable_by_moderator: true,
) )
subject.execute({}) job.execute({})
expect(ReviewableUser.count).to eq(1) expect(ReviewableUser.count).to eq(1)
expect(ReviewableUser.last).to eq(review_user) expect(ReviewableUser.last).to eq(review_user)
end end
it "adds a score" do it "adds a score" do
subject.execute({}) job.execute({})
score = ReviewableScore.last score = ReviewableScore.last
expect(score.reason).to eq("suspect_user") expect(score.reason).to eq("suspect_user")
@ -42,7 +44,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
it "only enqueues non-approved users" do it "only enqueues non-approved users" do
suspect_user.update!(approved: true) suspect_user.update!(approved: true)
subject.execute({}) job.execute({})
expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false) expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false)
end end
@ -51,7 +53,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
SiteSetting.must_approve_users = true SiteSetting.must_approve_users = true
suspect_user.update!(approved: false) suspect_user.update!(approved: false)
subject.execute({}) job.execute({})
expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false) expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false)
end end
@ -59,7 +61,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
it "ignores users created more than six months ago" do it "ignores users created more than six months ago" do
suspect_user.update!(created_at: 1.year.ago) suspect_user.update!(created_at: 1.year.ago)
subject.execute({}) job.execute({})
expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false) expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false)
end end
@ -67,7 +69,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
it "ignores users that were imported from another site" do it "ignores users that were imported from another site" do
suspect_user.upsert_custom_fields({ import_id: "fake_id" }) suspect_user.upsert_custom_fields({ import_id: "fake_id" })
subject.execute({}) job.execute({})
expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false) expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false)
end end
@ -75,7 +77,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
it "enqueues a suspect users with custom fields" do it "enqueues a suspect users with custom fields" do
suspect_user.upsert_custom_fields({ field_a: "value", field_b: "value" }) suspect_user.upsert_custom_fields({ field_a: "value", field_b: "value" })
subject.execute({}) job.execute({})
expect(ReviewableUser.where(target: suspect_user).exists?).to eq(true) expect(ReviewableUser.where(target: suspect_user).exists?).to eq(true)
end end
@ -85,7 +87,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
{ field_a: "value", field_b: "value", import_id: "fake_id" }, { field_a: "value", field_b: "value", import_id: "fake_id" },
) )
subject.execute({}) job.execute({})
expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false) expect(ReviewableUser.where(target: suspect_user).exists?).to eq(false)
end end
@ -97,7 +99,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
time_read: 30.seconds.to_i, time_read: 30.seconds.to_i,
) )
subject.execute({}) job.execute({})
expect(ReviewableUser.count).to eq(1) expect(ReviewableUser.count).to eq(1)
end end
@ -109,7 +111,7 @@ RSpec.describe Jobs::EnqueueSuspectUsers do
time_read: 2.minutes.to_i, time_read: 2.minutes.to_i,
) )
subject.execute({}) job.execute({})
expect(ReviewableUser.count).to eq(0) expect(ReviewableUser.count).to eq(0)
end end

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::EnsureS3UploadsExistence do RSpec.describe Jobs::EnsureS3UploadsExistence do
subject(:job) { described_class.new }
context "with S3 inventory enabled" do context "with S3 inventory enabled" do
before do before do
setup_s3 setup_s3
@ -9,21 +11,21 @@ RSpec.describe Jobs::EnsureS3UploadsExistence do
it "works" do it "works" do
S3Inventory.any_instance.expects(:backfill_etags_and_list_missing).once S3Inventory.any_instance.expects(:backfill_etags_and_list_missing).once
subject.execute({}) job.execute({})
end end
it "doesn't execute when the site was restored within the last 48 hours" do it "doesn't execute when the site was restored within the last 48 hours" do
S3Inventory.any_instance.expects(:backfill_etags_and_list_missing).never S3Inventory.any_instance.expects(:backfill_etags_and_list_missing).never
BackupMetadata.update_last_restore_date(47.hours.ago) BackupMetadata.update_last_restore_date(47.hours.ago)
subject.execute({}) job.execute({})
end end
it "executes when the site was restored more than 48 hours ago" do it "executes when the site was restored more than 48 hours ago" do
S3Inventory.any_instance.expects(:backfill_etags_and_list_missing).once S3Inventory.any_instance.expects(:backfill_etags_and_list_missing).once
BackupMetadata.update_last_restore_date(49.hours.ago) BackupMetadata.update_last_restore_date(49.hours.ago)
subject.execute({}) job.execute({})
end end
end end
@ -32,7 +34,7 @@ RSpec.describe Jobs::EnsureS3UploadsExistence do
it "doesn't execute" do it "doesn't execute" do
S3Inventory.any_instance.expects(:backfill_etags_and_list_missing).never S3Inventory.any_instance.expects(:backfill_etags_and_list_missing).never
subject.execute({}) job.execute({})
end end
end end
end end

View File

@ -1,17 +1,17 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::IgnoredUsersSummary do RSpec.describe Jobs::IgnoredUsersSummary do
subject(:job) { Jobs::IgnoredUsersSummary.new.execute({}) }
before do before do
SiteSetting.ignored_users_count_message_threshold = 1 SiteSetting.ignored_users_count_message_threshold = 1
SiteSetting.ignored_users_message_gap_days = 365 SiteSetting.ignored_users_message_gap_days = 365
end end
subject { Jobs::IgnoredUsersSummary.new.execute({}) }
context "with no ignored users" do context "with no ignored users" do
it "does nothing" do it "does nothing" do
subject job
expect { subject }.to_not change { Post.count } expect { job }.to_not change { Post.count }
end end
end end
@ -30,14 +30,14 @@ RSpec.describe Jobs::IgnoredUsersSummary do
before { SiteSetting.ignored_users_count_message_threshold = 5 } before { SiteSetting.ignored_users_count_message_threshold = 5 }
it "does nothing" do it "does nothing" do
subject job
expect { subject }.to_not change { Post.count } expect { job }.to_not change { Post.count }
end end
end end
context "when threshold is hit" do context "when threshold is hit" do
it "creates a system message" do it "creates a system message" do
subject job
posts = posts =
Post.joins(:topic).where( Post.joins(:topic).where(
topics: { topics: {
@ -57,15 +57,15 @@ RSpec.describe Jobs::IgnoredUsersSummary do
before { SiteSetting.ignored_users_count_message_threshold = 5 } before { SiteSetting.ignored_users_count_message_threshold = 5 }
it "does nothing" do it "does nothing" do
subject job
expect { subject }.to_not change { Post.count } expect { job }.to_not change { Post.count }
end end
end end
context "when threshold is hit" do context "when threshold is hit" do
it "does nothing" do it "does nothing" do
subject job
expect { subject }.to_not change { Post.count } expect { job }.to_not change { Post.count }
end end
end end
end end

View File

@ -1,14 +1,15 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::InvalidateInactiveAdmins do RSpec.describe Jobs::InvalidateInactiveAdmins do
fab!(:active_admin) { Fabricate(:admin, last_seen_at: 1.hour.ago) } subject(:job) { Jobs::InvalidateInactiveAdmins.new.execute({}) }
before { active_admin.email_tokens.update_all(confirmed: true) }
subject { Jobs::InvalidateInactiveAdmins.new.execute({}) } fab!(:active_admin) { Fabricate(:admin, last_seen_at: 1.hour.ago) }
before { active_admin.email_tokens.update_all(confirmed: true) }
it "does nothing when all admins have been seen recently" do it "does nothing when all admins have been seen recently" do
SiteSetting.invalidate_inactive_admin_email_after_days = 365 SiteSetting.invalidate_inactive_admin_email_after_days = 365
subject job
expect(active_admin.reload.active).to eq(true) expect(active_admin.reload.active).to eq(true)
expect(active_admin.email_tokens.where(confirmed: true).exists?).to eq(true) expect(active_admin.email_tokens.where(confirmed: true).exists?).to eq(true)
end end
@ -21,12 +22,12 @@ RSpec.describe Jobs::InvalidateInactiveAdmins do
before { SiteSetting.invalidate_inactive_admin_email_after_days = 365 } before { SiteSetting.invalidate_inactive_admin_email_after_days = 365 }
it "marks email tokens as unconfirmed" do it "marks email tokens as unconfirmed" do
subject job
expect(not_seen_admin.reload.email_tokens.where(confirmed: true).exists?).to eq(false) expect(not_seen_admin.reload.email_tokens.where(confirmed: true).exists?).to eq(false)
end end
it "makes the user as not active and logs the action" do it "makes the user as not active and logs the action" do
subject job
expect(not_seen_admin.reload.active).to eq(false) expect(not_seen_admin.reload.active).to eq(false)
log = UserHistory.last log = UserHistory.last
@ -35,7 +36,7 @@ RSpec.describe Jobs::InvalidateInactiveAdmins do
end end
it "adds a staff log" do it "adds a staff log" do
subject job
expect(not_seen_admin.reload.active).to eq(false) expect(not_seen_admin.reload.active).to eq(false)
end end
@ -52,20 +53,20 @@ RSpec.describe Jobs::InvalidateInactiveAdmins do
end end
it "removes the social logins" do it "removes the social logins" do
subject job
expect(UserAssociatedAccount.where(user_id: not_seen_admin.id).exists?).to eq(false) expect(UserAssociatedAccount.where(user_id: not_seen_admin.id).exists?).to eq(false)
end end
end end
it "doesn't deactivate admins with recent posts" do it "doesn't deactivate admins with recent posts" do
Fabricate(:post, user: not_seen_admin) Fabricate(:post, user: not_seen_admin)
subject job
expect(not_seen_admin.reload.active).to eq(true) expect(not_seen_admin.reload.active).to eq(true)
end end
it "doesn't deactivate admins with recently used api keys" do it "doesn't deactivate admins with recently used api keys" do
Fabricate(:api_key, user: not_seen_admin, last_used_at: 1.day.ago) Fabricate(:api_key, user: not_seen_admin, last_used_at: 1.day.ago)
subject job
expect(not_seen_admin.reload.active).to eq(true) expect(not_seen_admin.reload.active).to eq(true)
end end
end end
@ -74,7 +75,7 @@ RSpec.describe Jobs::InvalidateInactiveAdmins do
before { SiteSetting.invalidate_inactive_admin_email_after_days = 0 } before { SiteSetting.invalidate_inactive_admin_email_after_days = 0 }
it "does nothing" do it "does nothing" do
subject job
expect(active_admin.reload.active).to eq(true) expect(active_admin.reload.active).to eq(true)
expect(active_admin.email_tokens.where(confirmed: true).exists?).to eq(true) expect(active_admin.email_tokens.where(confirmed: true).exists?).to eq(true)
expect(not_seen_admin.reload.active).to eq(true) expect(not_seen_admin.reload.active).to eq(true)

View File

@ -1,16 +1,18 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::PostUpdateTopicTrackingState do RSpec.describe Jobs::PostUpdateTopicTrackingState do
subject(:job) { described_class.new }
fab!(:post) { Fabricate(:post) } fab!(:post) { Fabricate(:post) }
it "should publish messages" do it "should publish messages" do
messages = MessageBus.track_publish { subject.execute({ post_id: post.id }) } messages = MessageBus.track_publish { job.execute({ post_id: post.id }) }
expect(messages.size).not_to eq(0) expect(messages.size).not_to eq(0)
end end
it "should not publish messages for deleted topics" do it "should not publish messages for deleted topics" do
post.topic.trash! post.topic.trash!
messages = MessageBus.track_publish { subject.execute({ post_id: post.id }) } messages = MessageBus.track_publish { job.execute({ post_id: post.id }) }
expect(messages.size).to eq(0) expect(messages.size).to eq(0)
end end
end end

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::ProcessShelvedNotifications do RSpec.describe Jobs::ProcessShelvedNotifications do
subject(:job) { described_class.new }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
let(:post) { Fabricate(:post) } let(:post) { Fabricate(:post) }
@ -8,7 +10,7 @@ RSpec.describe Jobs::ProcessShelvedNotifications do
future = Fabricate(:do_not_disturb_timing, ends_at: 1.day.from_now) future = Fabricate(:do_not_disturb_timing, ends_at: 1.day.from_now)
past = Fabricate(:do_not_disturb_timing, starts_at: 2.day.ago, ends_at: 1.minute.ago) past = Fabricate(:do_not_disturb_timing, starts_at: 2.day.ago, ends_at: 1.minute.ago)
expect { subject.execute({}) }.to change { DoNotDisturbTiming.count }.by (-1) expect { job.execute({}) }.to change { DoNotDisturbTiming.count }.by (-1)
expect(DoNotDisturbTiming.find_by(id: future.id)).to eq(future) expect(DoNotDisturbTiming.find_by(id: future.id)).to eq(future)
expect(DoNotDisturbTiming.find_by(id: past.id)).to eq(nil) expect(DoNotDisturbTiming.find_by(id: past.id)).to eq(nil)
end end
@ -25,7 +27,7 @@ RSpec.describe Jobs::ProcessShelvedNotifications do
notification_type: 1, notification_type: 1,
) )
expect(notification.shelved_notification).to be_present expect(notification.shelved_notification).to be_present
subject.execute({}) job.execute({})
expect(notification.shelved_notification).to be_present expect(notification.shelved_notification).to be_present
end end
@ -43,7 +45,7 @@ RSpec.describe Jobs::ProcessShelvedNotifications do
user.do_not_disturb_timings.last.update(ends_at: 1.days.ago) user.do_not_disturb_timings.last.update(ends_at: 1.days.ago)
expect(notification.shelved_notification).to be_present expect(notification.shelved_notification).to be_present
subject.execute({}) job.execute({})
expect { notification.shelved_notification.reload }.to raise_error(ActiveRecord::RecordNotFound) expect { notification.shelved_notification.reload }.to raise_error(ActiveRecord::RecordNotFound)
end end
end end

View File

@ -472,25 +472,25 @@ RSpec.describe Jobs::PullHotlinkedImages do
end end
describe "#should_download_image?" do describe "#should_download_image?" do
subject { described_class.new } subject(:job) { described_class.new }
describe "when url is invalid" do describe "when url is invalid" do
it "should return false" do it "should return false" do
expect(subject.should_download_image?("null")).to eq(false) expect(job.should_download_image?("null")).to eq(false)
expect(subject.should_download_image?("meta.discourse.org")).to eq(false) expect(job.should_download_image?("meta.discourse.org")).to eq(false)
end end
end end
describe "when url is valid" do describe "when url is valid" do
it "should return true" do it "should return true" do
expect(subject.should_download_image?("http://meta.discourse.org")).to eq(true) expect(job.should_download_image?("http://meta.discourse.org")).to eq(true)
expect(subject.should_download_image?("//meta.discourse.org")).to eq(true) expect(job.should_download_image?("//meta.discourse.org")).to eq(true)
end end
end end
describe "when url is an upload" do describe "when url is an upload" do
it "should return false for original" do it "should return false for original" do
expect(subject.should_download_image?(Fabricate(:upload).url)).to eq(false) expect(job.should_download_image?(Fabricate(:upload).url)).to eq(false)
end end
context "when secure uploads enabled" do context "when secure uploads enabled" do
@ -501,19 +501,19 @@ RSpec.describe Jobs::PullHotlinkedImages do
upload = Fabricate(:upload_s3, secure: true) upload = Fabricate(:upload_s3, secure: true)
stub_s3(upload) stub_s3(upload)
url = Upload.secure_uploads_url_from_upload_url(upload.url) url = Upload.secure_uploads_url_from_upload_url(upload.url)
expect(subject.should_download_image?(url)).to eq(false) expect(job.should_download_image?(url)).to eq(false)
end end
end end
it "should return true for optimized" do it "should return true for optimized" do
src = Discourse.store.get_path_for_optimized_image(Fabricate(:optimized_image)) src = Discourse.store.get_path_for_optimized_image(Fabricate(:optimized_image))
expect(subject.should_download_image?(src)).to eq(true) expect(job.should_download_image?(src)).to eq(true)
end end
end end
it "returns false for emoji" do it "returns false for emoji" do
src = Emoji.url_for("testemoji.png") src = Emoji.url_for("testemoji.png")
expect(subject.should_download_image?(src)).to eq(false) expect(job.should_download_image?(src)).to eq(false)
end end
it "returns false for emoji when app and S3 CDNs configured" do it "returns false for emoji when app and S3 CDNs configured" do
@ -522,14 +522,14 @@ RSpec.describe Jobs::PullHotlinkedImages do
set_cdn_url "https://mydomain.cdn/test" set_cdn_url "https://mydomain.cdn/test"
src = UrlHelper.cook_url(Emoji.url_for("testemoji.png")) src = UrlHelper.cook_url(Emoji.url_for("testemoji.png"))
expect(subject.should_download_image?(src)).to eq(false) expect(job.should_download_image?(src)).to eq(false)
end end
it "returns false for emoji when emoji CDN configured" do it "returns false for emoji when emoji CDN configured" do
SiteSetting.external_emoji_url = "https://emoji.cdn.com" SiteSetting.external_emoji_url = "https://emoji.cdn.com"
src = UrlHelper.cook_url(Emoji.url_for("testemoji.png")) src = UrlHelper.cook_url(Emoji.url_for("testemoji.png"))
expect(subject.should_download_image?(src)).to eq(false) expect(job.should_download_image?(src)).to eq(false)
end end
it "returns false for emoji when app, S3 *and* emoji CDNs configured" do it "returns false for emoji when app, S3 *and* emoji CDNs configured" do
@ -539,17 +539,17 @@ RSpec.describe Jobs::PullHotlinkedImages do
set_cdn_url "https://mydomain.cdn/test" set_cdn_url "https://mydomain.cdn/test"
src = UrlHelper.cook_url(Emoji.url_for("testemoji.png")) src = UrlHelper.cook_url(Emoji.url_for("testemoji.png"))
expect(subject.should_download_image?(src)).to eq(false) expect(job.should_download_image?(src)).to eq(false)
end end
it "returns false for plugin assets" do it "returns false for plugin assets" do
src = UrlHelper.cook_url("/plugins/discourse-amazing-plugin/myasset.png") src = UrlHelper.cook_url("/plugins/discourse-amazing-plugin/myasset.png")
expect(subject.should_download_image?(src)).to eq(false) expect(job.should_download_image?(src)).to eq(false)
end end
it "returns false for local non-uploaded files" do it "returns false for local non-uploaded files" do
src = UrlHelper.cook_url("/mycustomroute.png") src = UrlHelper.cook_url("/mycustomroute.png")
expect(subject.should_download_image?(src)).to eq(false) expect(job.should_download_image?(src)).to eq(false)
end end
context "when download_remote_images_to_local? is false" do context "when download_remote_images_to_local? is false" do
@ -557,11 +557,11 @@ RSpec.describe Jobs::PullHotlinkedImages do
it "still returns true for optimized" do it "still returns true for optimized" do
src = Discourse.store.get_path_for_optimized_image(Fabricate(:optimized_image)) src = Discourse.store.get_path_for_optimized_image(Fabricate(:optimized_image))
expect(subject.should_download_image?(src)).to eq(true) expect(job.should_download_image?(src)).to eq(true)
end end
it "returns false for valid remote URLs" do it "returns false for valid remote URLs" do
expect(subject.should_download_image?("http://meta.discourse.org")).to eq(false) expect(job.should_download_image?("http://meta.discourse.org")).to eq(false)
end end
end end
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::PurgeExpiredIgnoredUsers do RSpec.describe Jobs::PurgeExpiredIgnoredUsers do
subject { Jobs::PurgeExpiredIgnoredUsers.new.execute({}) } subject(:job) { Jobs::PurgeExpiredIgnoredUsers.new.execute({}) }
context "with no ignored users" do context "with no ignored users" do
it "does nothing" do it "does nothing" do
expect { subject }.to_not change { IgnoredUser.count } expect { job }.to_not change { IgnoredUser.count }
end end
end end
@ -21,7 +21,7 @@ RSpec.describe Jobs::PurgeExpiredIgnoredUsers do
context "when no expired ignored users" do context "when no expired ignored users" do
it "does nothing" do it "does nothing" do
expect { subject }.to_not change { IgnoredUser.count } expect { job }.to_not change { IgnoredUser.count }
end end
end end
@ -32,7 +32,7 @@ RSpec.describe Jobs::PurgeExpiredIgnoredUsers do
Fabricate(:ignored_user, user: tarek, ignored_user: fred, expiring_at: 1.month.from_now) Fabricate(:ignored_user, user: tarek, ignored_user: fred, expiring_at: 1.month.from_now)
freeze_time(2.months.from_now) do freeze_time(2.months.from_now) do
subject job
expect(IgnoredUser.find_by(ignored_user: fred)).to be_nil expect(IgnoredUser.find_by(ignored_user: fred)).to be_nil
end end
end end

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::GroupSmtpEmail do RSpec.describe Jobs::GroupSmtpEmail do
subject(:job) { described_class.new }
fab!(:topic) { Fabricate(:private_message_topic, title: "Help I need support") } fab!(:topic) { Fabricate(:private_message_topic, title: "Help I need support") }
fab!(:post) do fab!(:post) do
Fabricate(:post, topic: topic, raw: "some first post content") Fabricate(:post, topic: topic, raw: "some first post content")
@ -46,11 +48,11 @@ RSpec.describe Jobs::GroupSmtpEmail do
bcc_addresses: [], bcc_addresses: [],
) )
.returns(message) .returns(message)
subject.execute(args) job.execute(args)
end end
it "includes a 'reply above this line' message" do it "includes a 'reply above this line' message" do
subject.execute(args) job.execute(args)
email_log = email_log =
EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id) EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
expect(email_log.as_mail_message.html_part.to_s).to include( expect(email_log.as_mail_message.html_part.to_s).to include(
@ -59,7 +61,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "does not include context posts" do it "does not include context posts" do
subject.execute(args) job.execute(args)
email_log = email_log =
EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id) EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
expect(email_log.as_mail_message.text_part.to_s).not_to include( expect(email_log.as_mail_message.text_part.to_s).not_to include(
@ -72,7 +74,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
second_post = topic.posts.find_by(post_number: 2) second_post = topic.posts.find_by(post_number: 2)
post.update!(reply_to_post_number: 1, reply_to_user: second_post.user) post.update!(reply_to_post_number: 1, reply_to_user: second_post.user)
PostReply.create(post: second_post, reply: post) PostReply.create(post: second_post, reply: post)
subject.execute(args) job.execute(args)
email_log = email_log =
EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id) EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
expect(email_log.raw_headers).to include( expect(email_log.raw_headers).to include(
@ -84,7 +86,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "includes the participants in the correct format (but not the recipient user), and does not have links for the staged users" do it "includes the participants in the correct format (but not the recipient user), and does not have links for the staged users" do
subject.execute(args) job.execute(args)
email_log = email_log =
EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id) EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
email_text = email_log.as_mail_message.text_part.to_s email_text = email_log.as_mail_message.text_part.to_s
@ -98,7 +100,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "creates an EmailLog record with the correct details" do it "creates an EmailLog record with the correct details" do
subject.execute(args) job.execute(args)
email_log = email_log =
EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id) EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
expect(email_log).not_to eq(nil) expect(email_log).not_to eq(nil)
@ -106,7 +108,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "creates an IncomingEmail record with the correct details to avoid double processing IMAP" do it "creates an IncomingEmail record with the correct details to avoid double processing IMAP" do
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support") expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
incoming_email = incoming_email =
@ -120,7 +122,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "does not create a post reply key, it always replies to the group email_username" do it "does not create a post reply key, it always replies to the group email_username" do
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support") expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
email_log = email_log =
@ -132,7 +134,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "creates an EmailLog record with the correct details" do it "creates an EmailLog record with the correct details" do
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support") expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
email_log = email_log =
@ -142,7 +144,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "creates an IncomingEmail record with the correct details to avoid double processing IMAP" do it "creates an IncomingEmail record with the correct details to avoid double processing IMAP" do
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support") expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
incoming_email = incoming_email =
@ -156,7 +158,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "does not create a post reply key, it always replies to the group email_username" do it "does not create a post reply key, it always replies to the group email_username" do
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support") expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
email_log = email_log =
@ -169,7 +171,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
it "falls back to the group name if full name is blank" do it "falls back to the group name if full name is blank" do
group.update(full_name: "") group.update(full_name: "")
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support") expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
email_log = email_log =
@ -178,7 +180,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
end end
it "has the group_smtp_id and the to_address filled in correctly" do it "has the group_smtp_id and the to_address filled in correctly" do
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support") expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
email_log = email_log =
@ -190,7 +192,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
it "drops malformed cc addresses when sending the email" do it "drops malformed cc addresses when sending the email" do
args2 = args.clone args2 = args.clone
args2[:cc_emails] << "somebadccemail@test.com<mailto:somebadccemail@test.com" args2[:cc_emails] << "somebadccemail@test.com<mailto:somebadccemail@test.com"
subject.execute(args2) job.execute(args2)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
last_email = ActionMailer::Base.deliveries.last last_email = ActionMailer::Base.deliveries.last
expect(last_email.subject).to eq("Re: Help I need support") expect(last_email.subject).to eq("Re: Help I need support")
@ -199,7 +201,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
context "when there are cc_addresses" do context "when there are cc_addresses" do
it "has the cc_addresses and cc_user_ids filled in correctly" do it "has the cc_addresses and cc_user_ids filled in correctly" do
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
sent_mail = ActionMailer::Base.deliveries.last sent_mail = ActionMailer::Base.deliveries.last
expect(sent_mail.subject).to eq("Re: Help I need support") expect(sent_mail.subject).to eq("Re: Help I need support")
@ -212,7 +214,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
it "where cc_addresses match non-staged users, convert to bcc_addresses" do it "where cc_addresses match non-staged users, convert to bcc_addresses" do
staged2.update!(staged: false, active: true) staged2.update!(staged: false, active: true)
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
sent_mail = ActionMailer::Base.deliveries.last sent_mail = ActionMailer::Base.deliveries.last
expect(sent_mail.subject).to eq("Re: Help I need support") expect(sent_mail.subject).to eq("Re: Help I need support")
@ -233,7 +235,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
before { group.update!(imap_enabled: true) } before { group.update!(imap_enabled: true) }
it "aborts and does not send a group SMTP email; the OP is the one that sent the email in the first place" do it "aborts and does not send a group SMTP email; the OP is the one that sent the email in the first place" do
expect { subject.execute(args) }.not_to(change { EmailLog.count }) expect { job.execute(args) }.not_to(change { EmailLog.count })
expect(ActionMailer::Base.deliveries.count).to eq(0) expect(ActionMailer::Base.deliveries.count).to eq(0)
end end
end end
@ -242,7 +244,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
before { group.update!(imap_enabled: false) } before { group.update!(imap_enabled: false) }
it "sends the email as expected" do it "sends the email as expected" do
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(1) expect(ActionMailer::Base.deliveries.count).to eq(1)
end end
end end
@ -251,7 +253,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
context "when the post is deleted" do context "when the post is deleted" do
it "aborts and adds a skipped email log" do it "aborts and adds a skipped email log" do
post.trash! post.trash!
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(0) expect(ActionMailer::Base.deliveries.count).to eq(0)
expect( expect(
SkippedEmailLog.exists?( SkippedEmailLog.exists?(
@ -268,7 +270,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
context "when the topic is deleted" do context "when the topic is deleted" do
it "aborts and adds a skipped email log" do it "aborts and adds a skipped email log" do
post.topic.trash! post.topic.trash!
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(0) expect(ActionMailer::Base.deliveries.count).to eq(0)
expect( expect(
SkippedEmailLog.exists?( SkippedEmailLog.exists?(
@ -285,7 +287,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
context "when smtp is not enabled" do context "when smtp is not enabled" do
it "returns without sending email" do it "returns without sending email" do
SiteSetting.enable_smtp = false SiteSetting.enable_smtp = false
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(0) expect(ActionMailer::Base.deliveries.count).to eq(0)
end end
end end
@ -293,7 +295,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
context "when disable_emails is yes" do context "when disable_emails is yes" do
it "returns without sending email" do it "returns without sending email" do
SiteSetting.disable_emails = "yes" SiteSetting.disable_emails = "yes"
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(0) expect(ActionMailer::Base.deliveries.count).to eq(0)
end end
end end
@ -301,7 +303,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
context "when group is deleted" do context "when group is deleted" do
it "returns without sending email" do it "returns without sending email" do
group.destroy group.destroy
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(0) expect(ActionMailer::Base.deliveries.count).to eq(0)
end end
end end
@ -309,7 +311,7 @@ RSpec.describe Jobs::GroupSmtpEmail do
context "when smtp is not enabled for the group" do context "when smtp is not enabled for the group" do
it "returns without sending email" do it "returns without sending email" do
group.update!(smtp_enabled: false) group.update!(smtp_enabled: false)
subject.execute(args) job.execute(args)
expect(ActionMailer::Base.deliveries.count).to eq(0) expect(ActionMailer::Base.deliveries.count).to eq(0)
expect( expect(
SkippedEmailLog.exists?( SkippedEmailLog.exists?(

View File

@ -1,13 +1,15 @@
# frozen_string_literal: true # frozen_string_literal: true
describe Jobs::PublishGroupMembershipUpdates do describe Jobs::PublishGroupMembershipUpdates do
subject(:job) { described_class.new }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
fab!(:group) { Fabricate(:group) } fab!(:group) { Fabricate(:group) }
it "publishes events for added users" do it "publishes events for added users" do
events = events =
DiscourseEvent.track_events do DiscourseEvent.track_events do
subject.execute(user_ids: [user.id], group_id: group.id, type: "add") job.execute(user_ids: [user.id], group_id: group.id, type: "add")
end end
expect(events).to include( expect(events).to include(
@ -19,7 +21,7 @@ describe Jobs::PublishGroupMembershipUpdates do
it "publishes events for removed users" do it "publishes events for removed users" do
events = events =
DiscourseEvent.track_events do DiscourseEvent.track_events do
subject.execute(user_ids: [user.id], group_id: group.id, type: "remove") job.execute(user_ids: [user.id], group_id: group.id, type: "remove")
end end
expect(events).to include(event_name: :user_removed_from_group, params: [user, group]) expect(events).to include(event_name: :user_removed_from_group, params: [user, group])
@ -27,9 +29,7 @@ describe Jobs::PublishGroupMembershipUpdates do
it "does nothing if the group doesn't exist" do it "does nothing if the group doesn't exist" do
events = events =
DiscourseEvent.track_events do DiscourseEvent.track_events { job.execute(user_ids: [user.id], group_id: nil, type: "add") }
subject.execute(user_ids: [user.id], group_id: nil, type: "add")
end
expect(events).not_to include( expect(events).not_to include(
event_name: :user_added_to_group, event_name: :user_added_to_group,
@ -38,7 +38,7 @@ describe Jobs::PublishGroupMembershipUpdates do
end end
it "fails when the update type is invalid" do it "fails when the update type is invalid" do
expect { subject.execute(user_ids: [user.id], group_id: nil, type: nil) }.to raise_error( expect { job.execute(user_ids: [user.id], group_id: nil, type: nil) }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
) )
end end
@ -46,7 +46,7 @@ describe Jobs::PublishGroupMembershipUpdates do
it "does nothing when the user is not human" do it "does nothing when the user is not human" do
events = events =
DiscourseEvent.track_events do DiscourseEvent.track_events do
subject.execute(user_ids: [Discourse.system_user.id], group_id: nil, type: "add") job.execute(user_ids: [Discourse.system_user.id], group_id: nil, type: "add")
end end
expect(events).not_to include( expect(events).not_to include(

View File

@ -1,12 +1,15 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::ReindexSearch do RSpec.describe Jobs::ReindexSearch do
subject(:job) { described_class.new }
let(:locale) { "fr" }
before do before do
SearchIndexer.enable SearchIndexer.enable
Jobs.run_immediately! Jobs.run_immediately!
end end
let(:locale) { "fr" }
# This works since test db has a small record less than limit. # This works since test db has a small record less than limit.
# Didn't check `topic` because topic doesn't have posts in fabrication # Didn't check `topic` because topic doesn't have posts in fabrication
# thus no search data # thus no search data
@ -15,7 +18,7 @@ RSpec.describe Jobs::ReindexSearch do
SiteSetting.default_locale = "en" SiteSetting.default_locale = "en"
model = Fabricate(m.to_sym) model = Fabricate(m.to_sym)
SiteSetting.default_locale = locale SiteSetting.default_locale = locale
subject.execute({}) job.execute({})
expect(model.public_send("#{m}_search_data").locale).to eq locale expect(model.public_send("#{m}_search_data").locale).to eq locale
end end
@ -26,7 +29,7 @@ RSpec.describe Jobs::ReindexSearch do
search_data.update!(version: 0) search_data.update!(version: 0)
model.reload model.reload
subject.execute({}) job.execute({})
expect(model.public_send("#{m}_search_data").version).to eq( expect(model.public_send("#{m}_search_data").version).to eq(
"SearchIndexer::#{m.upcase}_INDEX_VERSION".constantize, "SearchIndexer::#{m.upcase}_INDEX_VERSION".constantize,
) )
@ -64,7 +67,7 @@ RSpec.describe Jobs::ReindexSearch do
post2.topic.trash! post2.topic.trash!
post3.trash! post3.trash!
subject.rebuild_posts(indexer: FakeIndexer) job.rebuild_posts(indexer: FakeIndexer)
expect(FakeIndexer.posts).to contain_exactly(post) expect(FakeIndexer.posts).to contain_exactly(post)
end end
@ -72,7 +75,7 @@ RSpec.describe Jobs::ReindexSearch do
it "should not reindex posts with a developmental version" do it "should not reindex posts with a developmental version" do
Fabricate(:post, version: SearchIndexer::POST_INDEX_VERSION + 1) Fabricate(:post, version: SearchIndexer::POST_INDEX_VERSION + 1)
subject.rebuild_posts(indexer: FakeIndexer) job.rebuild_posts(indexer: FakeIndexer)
expect(FakeIndexer.posts).to eq([]) expect(FakeIndexer.posts).to eq([])
end end
@ -85,7 +88,7 @@ RSpec.describe Jobs::ReindexSearch do
post2.save!(validate: false) post2.save!(validate: false)
subject.rebuild_posts(indexer: FakeIndexer) job.rebuild_posts(indexer: FakeIndexer)
expect(FakeIndexer.posts).to contain_exactly(post) expect(FakeIndexer.posts).to contain_exactly(post)
end end
@ -100,7 +103,7 @@ RSpec.describe Jobs::ReindexSearch do
freeze_time(1.day.ago) { topic.trash! } freeze_time(1.day.ago) { topic.trash! }
expect { subject.execute({}) }.to change { TopicSearchData.count }.by(-1) expect { job.execute({}) }.to change { TopicSearchData.count }.by(-1)
expect(Topic.pluck(:id)).to contain_exactly(topic2.id) expect(Topic.pluck(:id)).to contain_exactly(topic2.id)
expect(TopicSearchData.pluck(:topic_id)).to contain_exactly(topic2.topic_search_data.topic_id) expect(TopicSearchData.pluck(:topic_id)).to contain_exactly(topic2.topic_search_data.topic_id)
@ -124,7 +127,7 @@ RSpec.describe Jobs::ReindexSearch do
post6.trash! post6.trash!
end end
expect { subject.execute({}) }.to change { PostSearchData.count }.by(-3) expect { job.execute({}) }.to change { PostSearchData.count }.by(-3)
expect(Post.pluck(:id)).to contain_exactly(post.id, post2.id, post3.id, post4.id, post5.id) expect(Post.pluck(:id)).to contain_exactly(post.id, post2.id, post3.id, post4.id, post5.id)

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::SyncTopicUserBookmarked do RSpec.describe Jobs::SyncTopicUserBookmarked do
subject(:job) { described_class.new }
fab!(:topic) { Fabricate(:topic) } fab!(:topic) { Fabricate(:topic) }
fab!(:post1) { Fabricate(:post, topic: topic) } fab!(:post1) { Fabricate(:post, topic: topic) }
fab!(:post2) { Fabricate(:post, topic: topic) } fab!(:post2) { Fabricate(:post, topic: topic) }
@ -16,7 +18,7 @@ RSpec.describe Jobs::SyncTopicUserBookmarked do
Fabricate(:bookmark, user: tu1.user, bookmarkable: topic.posts.sample) Fabricate(:bookmark, user: tu1.user, bookmarkable: topic.posts.sample)
Fabricate(:bookmark, user: tu4.user, bookmarkable: topic.posts.sample) Fabricate(:bookmark, user: tu4.user, bookmarkable: topic.posts.sample)
subject.execute(topic_id: topic.id) job.execute(topic_id: topic.id)
expect(tu1.reload.bookmarked).to eq(true) expect(tu1.reload.bookmarked).to eq(true)
expect(tu2.reload.bookmarked).to eq(false) expect(tu2.reload.bookmarked).to eq(false)
@ -31,7 +33,7 @@ RSpec.describe Jobs::SyncTopicUserBookmarked do
post1.trash! post1.trash!
subject.execute(topic_id: topic.id) job.execute(topic_id: topic.id)
expect(tu1.reload.bookmarked).to eq(false) expect(tu1.reload.bookmarked).to eq(false)
expect(tu2.reload.bookmarked).to eq(false) expect(tu2.reload.bookmarked).to eq(false)
@ -41,7 +43,7 @@ RSpec.describe Jobs::SyncTopicUserBookmarked do
Fabricate(:bookmark, user: tu1.user, bookmarkable: topic.posts.sample) Fabricate(:bookmark, user: tu1.user, bookmarkable: topic.posts.sample)
Fabricate(:bookmark, user: tu4.user, bookmarkable: topic.posts.sample) Fabricate(:bookmark, user: tu4.user, bookmarkable: topic.posts.sample)
subject.execute job.execute
expect(tu1.reload.bookmarked).to eq(true) expect(tu1.reload.bookmarked).to eq(true)
expect(tu2.reload.bookmarked).to eq(false) expect(tu2.reload.bookmarked).to eq(false)

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Jobs::TopicTimerEnqueuer do RSpec.describe Jobs::TopicTimerEnqueuer do
subject { described_class.new } subject(:job) { described_class.new }
fab!(:timer1) do fab!(:timer1) do
Fabricate( Fabricate(
@ -40,20 +40,20 @@ RSpec.describe Jobs::TopicTimerEnqueuer do
it "does not enqueue deleted timers" do it "does not enqueue deleted timers" do
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: deleted_timer.id }) expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: deleted_timer.id })
subject.execute job.execute
expect(deleted_timer.topic.reload.closed?).to eq(false) expect(deleted_timer.topic.reload.closed?).to eq(false)
end end
it "does not enqueue future timers" do it "does not enqueue future timers" do
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: future_timer.id }) expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: future_timer.id })
subject.execute job.execute
expect(future_timer.topic.reload.closed?).to eq(false) expect(future_timer.topic.reload.closed?).to eq(false)
end end
it "enqueues the related job" do it "enqueues the related job" do
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: deleted_timer.id }) expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: deleted_timer.id })
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: future_timer.id }) expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: future_timer.id })
subject.execute job.execute
expect_job_enqueued(job: :close_topic, args: { topic_timer_id: timer1.id }) expect_job_enqueued(job: :close_topic, args: { topic_timer_id: timer1.id })
expect_job_enqueued(job: :open_topic, args: { topic_timer_id: timer2.id }) expect_job_enqueued(job: :open_topic, args: { topic_timer_id: timer2.id })
end end
@ -61,11 +61,11 @@ RSpec.describe Jobs::TopicTimerEnqueuer do
it "does not re-enqueue a job that has already been scheduled ahead of time in sidekiq (legacy topic timers)" do it "does not re-enqueue a job that has already been scheduled ahead of time in sidekiq (legacy topic timers)" do
expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: timer1.id }) expect_not_enqueued_with(job: :close_topic, args: { topic_timer_id: timer1.id })
Jobs.enqueue_at(1.hours.from_now, :close_topic, topic_timer_id: timer1.id) Jobs.enqueue_at(1.hours.from_now, :close_topic, topic_timer_id: timer1.id)
subject.execute job.execute
end end
it "does not fail to enqueue other timers just because one timer errors" do it "does not fail to enqueue other timers just because one timer errors" do
TopicTimer.any_instance.stubs(:enqueue_typed_job).raises(StandardError).then.returns(true) TopicTimer.any_instance.stubs(:enqueue_typed_job).raises(StandardError).then.returns(true)
expect { subject.execute }.not_to raise_error expect { job.execute }.not_to raise_error
end end
end end

View File

@ -3,12 +3,12 @@
require_relative "shared_context_for_backup_restore" require_relative "shared_context_for_backup_restore"
RSpec.describe BackupRestore::DatabaseRestorer, type: :multisite do RSpec.describe BackupRestore::DatabaseRestorer, type: :multisite do
subject(:restorer) { BackupRestore::DatabaseRestorer.new(logger, current_db) }
include_context "with shared stuff" include_context "with shared stuff"
let(:current_db) { RailsMultisite::ConnectionManagement.current_db } let(:current_db) { RailsMultisite::ConnectionManagement.current_db }
subject { BackupRestore::DatabaseRestorer.new(logger, current_db) }
describe "#restore" do describe "#restore" do
context "with database connection" do context "with database connection" do
it "reconnects to the correct database" do it "reconnects to the correct database" do

View File

@ -3,12 +3,12 @@
require_relative "shared_context_for_backup_restore" require_relative "shared_context_for_backup_restore"
RSpec.describe BackupRestore::DatabaseRestorer do RSpec.describe BackupRestore::DatabaseRestorer do
subject(:restorer) { BackupRestore::DatabaseRestorer.new(logger, current_db) }
include_context "with shared stuff" include_context "with shared stuff"
let(:current_db) { RailsMultisite::ConnectionManagement.current_db } let(:current_db) { RailsMultisite::ConnectionManagement.current_db }
subject { BackupRestore::DatabaseRestorer.new(logger, current_db) }
describe "#restore" do describe "#restore" do
it "executes everything in the correct order" do it "executes everything in the correct order" do
restore = sequence("restore") restore = sequence("restore")
@ -18,7 +18,7 @@ RSpec.describe BackupRestore::DatabaseRestorer do
expect_db_migrate.in_sequence(restore) expect_db_migrate.in_sequence(restore)
expect_db_reconnect.in_sequence(restore) expect_db_reconnect.in_sequence(restore)
subject.restore("foo.sql") restorer.restore("foo.sql")
end end
it "stores the date of the last restore" do it "stores the date of the last restore" do
@ -146,12 +146,12 @@ RSpec.describe BackupRestore::DatabaseRestorer do
it "moves tables back when tables were moved" do it "moves tables back when tables were moved" do
BackupRestore.stubs(:can_rollback?).returns(true) BackupRestore.stubs(:can_rollback?).returns(true)
BackupRestore.expects(:move_tables_between_schemas).with("backup", "public").never BackupRestore.expects(:move_tables_between_schemas).with("backup", "public").never
subject.rollback restorer.rollback
execute_stubbed_restore execute_stubbed_restore
BackupRestore.expects(:move_tables_between_schemas).with("backup", "public").once BackupRestore.expects(:move_tables_between_schemas).with("backup", "public").once
subject.rollback restorer.rollback
end end
end end
@ -164,7 +164,7 @@ RSpec.describe BackupRestore::DatabaseRestorer do
it "doesn't try to drop function when no functions have been created" do it "doesn't try to drop function when no functions have been created" do
Migration::BaseDropper.expects(:drop_readonly_function).never Migration::BaseDropper.expects(:drop_readonly_function).never
subject.clean_up restorer.clean_up
end end
it "creates and drops all functions when none exist" do it "creates and drops all functions when none exist" do
@ -174,7 +174,7 @@ RSpec.describe BackupRestore::DatabaseRestorer do
Migration::BaseDropper.expects(:drop_readonly_function).with(:posts, :via_email) Migration::BaseDropper.expects(:drop_readonly_function).with(:posts, :via_email)
Migration::BaseDropper.expects(:drop_readonly_function).with(:posts, :raw_email) Migration::BaseDropper.expects(:drop_readonly_function).with(:posts, :raw_email)
subject.clean_up restorer.clean_up
end end
it "creates and drops only missing functions during restore" do it "creates and drops only missing functions during restore" do
@ -186,19 +186,17 @@ RSpec.describe BackupRestore::DatabaseRestorer do
execute_stubbed_restore(stub_readonly_functions: false) execute_stubbed_restore(stub_readonly_functions: false)
Migration::BaseDropper.expects(:drop_readonly_function).with(:posts, :via_email) Migration::BaseDropper.expects(:drop_readonly_function).with(:posts, :via_email)
subject.clean_up restorer.clean_up
end end
end end
describe ".drop_backup_schema" do describe ".drop_backup_schema" do
subject { BackupRestore::DatabaseRestorer }
context "when no backup schema exists" do context "when no backup schema exists" do
it "doesn't do anything" do it "doesn't do anything" do
ActiveRecord::Base.connection.expects(:schema_exists?).with("backup").returns(false) ActiveRecord::Base.connection.expects(:schema_exists?).with("backup").returns(false)
ActiveRecord::Base.connection.expects(:drop_schema).never ActiveRecord::Base.connection.expects(:drop_schema).never
subject.drop_backup_schema described_class.drop_backup_schema
end end
end end
@ -209,14 +207,14 @@ RSpec.describe BackupRestore::DatabaseRestorer do
ActiveRecord::Base.connection.expects(:drop_schema).with("backup") ActiveRecord::Base.connection.expects(:drop_schema).with("backup")
BackupMetadata.update_last_restore_date(8.days.ago) BackupMetadata.update_last_restore_date(8.days.ago)
subject.drop_backup_schema described_class.drop_backup_schema
end end
it "doesn't drop the schema when the last restore was recently" do it "doesn't drop the schema when the last restore was recently" do
ActiveRecord::Base.connection.expects(:drop_schema).with("backup").never ActiveRecord::Base.connection.expects(:drop_schema).with("backup").never
BackupMetadata.update_last_restore_date(6.days.ago) BackupMetadata.update_last_restore_date(6.days.ago)
subject.drop_backup_schema described_class.drop_backup_schema
end end
it "stores the current date when there is no record of the last restore" do it "stores the current date when there is no record of the last restore" do
@ -225,7 +223,7 @@ RSpec.describe BackupRestore::DatabaseRestorer do
date_string = "2020-01-08T17:38:27Z" date_string = "2020-01-08T17:38:27Z"
freeze_time(Time.parse(date_string)) freeze_time(Time.parse(date_string))
subject.drop_backup_schema described_class.drop_backup_schema
expect(BackupMetadata.value_for(BackupMetadata::LAST_RESTORE_DATE)).to eq(date_string) expect(BackupMetadata.value_for(BackupMetadata::LAST_RESTORE_DATE)).to eq(date_string)
end end
end end

View File

@ -4,6 +4,8 @@ require "backup_restore/local_backup_store"
require_relative "shared_examples_for_backup_store" require_relative "shared_examples_for_backup_store"
RSpec.describe BackupRestore::LocalBackupStore do RSpec.describe BackupRestore::LocalBackupStore do
subject(:store) { BackupRestore::BackupStore.create(root_directory: @root_directory) }
before do before do
@root_directory = Dir.mktmpdir @root_directory = Dir.mktmpdir
@paths = [] @paths = []
@ -12,7 +14,6 @@ RSpec.describe BackupRestore::LocalBackupStore do
after { FileUtils.remove_dir(@root_directory, true) } after { FileUtils.remove_dir(@root_directory, true) }
subject(:store) { BackupRestore::BackupStore.create(root_directory: @root_directory) }
let(:expected_type) { BackupRestore::LocalBackupStore } let(:expected_type) { BackupRestore::LocalBackupStore }
it_behaves_like "backup store" it_behaves_like "backup store"

View File

@ -5,6 +5,8 @@ require "backup_restore/s3_backup_store"
require_relative "shared_examples_for_backup_store" require_relative "shared_examples_for_backup_store"
RSpec.describe BackupRestore::S3BackupStore do RSpec.describe BackupRestore::S3BackupStore do
subject(:store) { BackupRestore::BackupStore.create(s3_options: @s3_options) }
before do before do
@s3_client = Aws::S3::Client.new(stub_responses: true) @s3_client = Aws::S3::Client.new(stub_responses: true)
@s3_options = { client: @s3_client } @s3_options = { client: @s3_client }
@ -86,7 +88,6 @@ RSpec.describe BackupRestore::S3BackupStore do
SiteSetting.backup_location = BackupLocationSiteSetting::S3 SiteSetting.backup_location = BackupLocationSiteSetting::S3
end end
subject(:store) { BackupRestore::BackupStore.create(s3_options: @s3_options) }
let(:expected_type) { BackupRestore::S3BackupStore } let(:expected_type) { BackupRestore::S3BackupStore }
it_behaves_like "backup store" it_behaves_like "backup store"

View File

@ -3,9 +3,9 @@
require_relative "shared_context_for_backup_restore" require_relative "shared_context_for_backup_restore"
RSpec.describe BackupRestore::SystemInterface, type: :multisite do RSpec.describe BackupRestore::SystemInterface, type: :multisite do
include_context "with shared stuff" subject(:system_interface) { BackupRestore::SystemInterface.new(logger) }
subject { BackupRestore::SystemInterface.new(logger) } include_context "with shared stuff"
describe "#flush_redis" do describe "#flush_redis" do
it "removes only keys from the current site in a multisite" do it "removes only keys from the current site in a multisite" do
@ -24,7 +24,7 @@ RSpec.describe BackupRestore::SystemInterface, type: :multisite do
expect(Discourse.redis.get("foo")).to eq("second-foo") expect(Discourse.redis.get("foo")).to eq("second-foo")
expect(Discourse.redis.get("bar")).to eq("second-bar") expect(Discourse.redis.get("bar")).to eq("second-bar")
subject.flush_redis system_interface.flush_redis
expect(Discourse.redis.get("foo")).to be_nil expect(Discourse.redis.get("foo")).to be_nil
expect(Discourse.redis.get("bar")).to be_nil expect(Discourse.redis.get("bar")).to be_nil
@ -43,7 +43,7 @@ RSpec.describe BackupRestore::SystemInterface, type: :multisite do
BackupRestore.mark_as_running! BackupRestore.mark_as_running!
expect do expect do
thread = subject.listen_for_shutdown_signal thread = system_interface.listen_for_shutdown_signal
BackupRestore.set_shutdown_signal! BackupRestore.set_shutdown_signal!
thread.join thread.join
end.to raise_error(SystemExit) end.to raise_error(SystemExit)

View File

@ -3,9 +3,9 @@
require_relative "shared_context_for_backup_restore" require_relative "shared_context_for_backup_restore"
RSpec.describe BackupRestore::SystemInterface do RSpec.describe BackupRestore::SystemInterface do
include_context "with shared stuff" subject(:system_interface) { BackupRestore::SystemInterface.new(logger) }
subject { BackupRestore::SystemInterface.new(logger) } include_context "with shared stuff"
describe "readonly mode" do describe "readonly mode" do
after { Discourse::READONLY_KEYS.each { |key| Discourse.redis.del(key) } } after { Discourse::READONLY_KEYS.each { |key| Discourse.redis.del(key) } }
@ -13,26 +13,26 @@ RSpec.describe BackupRestore::SystemInterface do
describe "#enable_readonly_mode" do describe "#enable_readonly_mode" do
it "enables readonly mode" do it "enables readonly mode" do
Discourse.expects(:enable_readonly_mode).once Discourse.expects(:enable_readonly_mode).once
subject.enable_readonly_mode system_interface.enable_readonly_mode
end end
it "does not enable readonly mode when it is already in readonly mode" do it "does not enable readonly mode when it is already in readonly mode" do
Discourse.enable_readonly_mode Discourse.enable_readonly_mode
Discourse.expects(:enable_readonly_mode).never Discourse.expects(:enable_readonly_mode).never
subject.enable_readonly_mode system_interface.enable_readonly_mode
end end
end end
describe "#disable_readonly_mode" do describe "#disable_readonly_mode" do
it "disables readonly mode" do it "disables readonly mode" do
Discourse.expects(:disable_readonly_mode).once Discourse.expects(:disable_readonly_mode).once
subject.disable_readonly_mode system_interface.disable_readonly_mode
end end
it "does not disable readonly mode when readonly mode was explicitly enabled" do it "does not disable readonly mode when readonly mode was explicitly enabled" do
Discourse.enable_readonly_mode Discourse.enable_readonly_mode
Discourse.expects(:disable_readonly_mode).never Discourse.expects(:disable_readonly_mode).never
subject.disable_readonly_mode system_interface.disable_readonly_mode
end end
end end
end end
@ -40,14 +40,14 @@ RSpec.describe BackupRestore::SystemInterface do
describe "#mark_restore_as_running" do describe "#mark_restore_as_running" do
it "calls mark_restore_as_running" do it "calls mark_restore_as_running" do
BackupRestore.expects(:mark_as_running!).once BackupRestore.expects(:mark_as_running!).once
subject.mark_restore_as_running system_interface.mark_restore_as_running
end end
end end
describe "#mark_restore_as_not_running" do describe "#mark_restore_as_not_running" do
it "calls mark_restore_as_not_running" do it "calls mark_restore_as_not_running" do
BackupRestore.expects(:mark_as_not_running!).once BackupRestore.expects(:mark_as_not_running!).once
subject.mark_restore_as_not_running system_interface.mark_restore_as_not_running
end end
end end
@ -61,7 +61,7 @@ RSpec.describe BackupRestore::SystemInterface do
it "exits the process when shutdown signal is set" do it "exits the process when shutdown signal is set" do
expect do expect do
thread = subject.listen_for_shutdown_signal thread = system_interface.listen_for_shutdown_signal
BackupRestore.set_shutdown_signal! BackupRestore.set_shutdown_signal!
thread.join thread.join
end.to raise_error(SystemExit) end.to raise_error(SystemExit)
@ -71,7 +71,7 @@ RSpec.describe BackupRestore::SystemInterface do
BackupRestore.set_shutdown_signal! BackupRestore.set_shutdown_signal!
expect(BackupRestore.should_shutdown?).to eq(true) expect(BackupRestore.should_shutdown?).to eq(true)
thread = subject.listen_for_shutdown_signal thread = system_interface.listen_for_shutdown_signal
expect(BackupRestore.should_shutdown?).to eq(false) expect(BackupRestore.should_shutdown?).to eq(false)
Thread.kill(thread) Thread.kill(thread)
end end
@ -82,7 +82,7 @@ RSpec.describe BackupRestore::SystemInterface do
it "calls pause!" do it "calls pause!" do
expect(Sidekiq.paused?).to eq(false) expect(Sidekiq.paused?).to eq(false)
subject.pause_sidekiq("my reason") system_interface.pause_sidekiq("my reason")
expect(Sidekiq.paused?).to eq(true) expect(Sidekiq.paused?).to eq(true)
expect(Discourse.redis.get(SidekiqPauser::PAUSED_KEY)).to eq("my reason") expect(Discourse.redis.get(SidekiqPauser::PAUSED_KEY)).to eq("my reason")
end end
@ -93,15 +93,15 @@ RSpec.describe BackupRestore::SystemInterface do
Sidekiq.pause! Sidekiq.pause!
expect(Sidekiq.paused?).to eq(true) expect(Sidekiq.paused?).to eq(true)
subject.unpause_sidekiq system_interface.unpause_sidekiq
expect(Sidekiq.paused?).to eq(false) expect(Sidekiq.paused?).to eq(false)
end end
end end
describe "#wait_for_sidekiq" do describe "#wait_for_sidekiq" do
it "waits 6 seconds even when there are no running Sidekiq jobs" do it "waits 6 seconds even when there are no running Sidekiq jobs" do
subject.expects(:sleep).with(6).once system_interface.expects(:sleep).with(6).once
subject.wait_for_sidekiq system_interface.wait_for_sidekiq
end end
context "with Sidekiq workers" do context "with Sidekiq workers" do
@ -146,22 +146,26 @@ RSpec.describe BackupRestore::SystemInterface do
end end
it "waits up to 60 seconds for jobs running for the current site to finish" do it "waits up to 60 seconds for jobs running for the current site to finish" do
subject.expects(:sleep).with(6).times(10) system_interface.expects(:sleep).with(6).times(10)
create_workers create_workers
expect { subject.wait_for_sidekiq }.to raise_error(BackupRestore::RunningSidekiqJobsError) expect { system_interface.wait_for_sidekiq }.to raise_error(
BackupRestore::RunningSidekiqJobsError,
)
end end
it "waits up to 60 seconds for jobs running on all sites to finish" do it "waits up to 60 seconds for jobs running on all sites to finish" do
subject.expects(:sleep).with(6).times(10) system_interface.expects(:sleep).with(6).times(10)
create_workers(all_sites: true) create_workers(all_sites: true)
expect { subject.wait_for_sidekiq }.to raise_error(BackupRestore::RunningSidekiqJobsError) expect { system_interface.wait_for_sidekiq }.to raise_error(
BackupRestore::RunningSidekiqJobsError,
)
end end
it "ignores jobs of other sites" do it "ignores jobs of other sites" do
subject.expects(:sleep).with(6).once system_interface.expects(:sleep).with(6).once
create_workers(site_id: "another_site") create_workers(site_id: "another_site")
subject.wait_for_sidekiq system_interface.wait_for_sidekiq
end end
end end
end end
@ -172,7 +176,7 @@ RSpec.describe BackupRestore::SystemInterface do
it "doesn't unpause Sidekiq" do it "doesn't unpause Sidekiq" do
Sidekiq.pause! Sidekiq.pause!
subject.flush_redis system_interface.flush_redis
expect(Sidekiq.paused?).to eq(true) expect(Sidekiq.paused?).to eq(true)
end end

View File

@ -4,9 +4,9 @@
require_relative "shared_context_for_backup_restore" require_relative "shared_context_for_backup_restore"
RSpec.describe BackupRestore::UploadsRestorer do RSpec.describe BackupRestore::UploadsRestorer do
include_context "with shared stuff" subject(:restorer) { BackupRestore::UploadsRestorer.new(logger) }
subject { BackupRestore::UploadsRestorer.new(logger) } include_context "with shared stuff"
def with_temp_uploads_directory(name: "default", with_optimized: false) def with_temp_uploads_directory(name: "default", with_optimized: false)
Dir.mktmpdir do |directory| Dir.mktmpdir do |directory|
@ -93,7 +93,7 @@ RSpec.describe BackupRestore::UploadsRestorer do
def setup_and_restore(directory, metadata) def setup_and_restore(directory, metadata)
metadata.each { |d| BackupMetadata.create!(d) } metadata.each { |d| BackupMetadata.create!(d) }
subject.restore(directory) restorer.restore(directory)
end end
def uploads_path(database) def uploads_path(database)
@ -119,15 +119,15 @@ RSpec.describe BackupRestore::UploadsRestorer do
let(:target_site_name) { target_site_type == multisite ? "second" : "default" } let(:target_site_name) { target_site_type == multisite ? "second" : "default" }
let(:target_hostname) { target_site_type == multisite ? "test2.localhost" : "test.localhost" } let(:target_hostname) { target_site_type == multisite ? "test2.localhost" : "test.localhost" }
shared_context "with no uploads" do shared_examples "with no uploads" do
it "does nothing when temporary uploads directory is missing or empty" do it "does nothing when temporary uploads directory is missing or empty" do
store_class.any_instance.expects(:copy_from).never store_class.any_instance.expects(:copy_from).never
Dir.mktmpdir do |directory| Dir.mktmpdir do |directory|
subject.restore(directory) restorer.restore(directory)
FileUtils.mkdir(File.join(directory, "uploads")) FileUtils.mkdir(File.join(directory, "uploads"))
subject.restore(directory) restorer.restore(directory)
end end
end end
end end
@ -176,7 +176,7 @@ RSpec.describe BackupRestore::UploadsRestorer do
with_temp_uploads_directory do |directory, path| with_temp_uploads_directory do |directory, path|
store_class.any_instance.expects(:copy_from).with(path).once store_class.any_instance.expects(:copy_from).with(path).once
expect { subject.restore(directory) }.to change { OptimizedImage.count }.by_at_most( expect { restorer.restore(directory) }.to change { OptimizedImage.count }.by_at_most(
-1, -1,
).and change { Jobs::CreateAvatarThumbnails.jobs.size }.by(1).and change { ).and change { Jobs::CreateAvatarThumbnails.jobs.size }.by(1).and change {
Post.where(baked_version: nil).count Post.where(baked_version: nil).count
@ -190,7 +190,7 @@ RSpec.describe BackupRestore::UploadsRestorer do
with_temp_uploads_directory(with_optimized: true) do |directory, path| with_temp_uploads_directory(with_optimized: true) do |directory, path|
store_class.any_instance.expects(:copy_from).with(path).once store_class.any_instance.expects(:copy_from).with(path).once
expect { subject.restore(directory) }.to not_change { expect { restorer.restore(directory) }.to not_change {
OptimizedImage.count OptimizedImage.count
}.and not_change { Jobs::CreateAvatarThumbnails.jobs.size }.and change { }.and not_change { Jobs::CreateAvatarThumbnails.jobs.size }.and change {
Post.where(baked_version: nil).count Post.where(baked_version: nil).count
@ -609,14 +609,14 @@ RSpec.describe BackupRestore::UploadsRestorer do
Discourse.stubs(:store).returns(Object.new) Discourse.stubs(:store).returns(Object.new)
with_temp_uploads_directory do |directory| with_temp_uploads_directory do |directory|
expect { subject.restore(directory) }.to raise_error(BackupRestore::UploadsRestoreError) expect { restorer.restore(directory) }.to raise_error(BackupRestore::UploadsRestoreError)
end end
end end
it "raises an exception when there are multiple folders in the uploads directory" do it "raises an exception when there are multiple folders in the uploads directory" do
with_temp_uploads_directory do |directory| with_temp_uploads_directory do |directory|
FileUtils.mkdir_p(File.join(directory, "uploads", "foo")) FileUtils.mkdir_p(File.join(directory, "uploads", "foo"))
expect { subject.restore(directory) }.to raise_error(BackupRestore::UploadsRestoreError) expect { restorer.restore(directory) }.to raise_error(BackupRestore::UploadsRestoreError)
end end
end end

View File

@ -1,25 +1,25 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe BookmarkManager do RSpec.describe BookmarkManager do
let(:user) { Fabricate(:user) } subject(:manager) { described_class.new(user) }
let(:reminder_at) { 1.day.from_now }
fab!(:post) { Fabricate(:post) } fab!(:post) { Fabricate(:post) }
let(:name) { "Check this out!" }
subject { described_class.new(user) } let(:user) { Fabricate(:user) }
let(:reminder_at) { 1.day.from_now }
let(:name) { "Check this out!" }
describe ".destroy" do describe ".destroy" do
let!(:bookmark) { Fabricate(:bookmark, user: user, bookmarkable: post) } let!(:bookmark) { Fabricate(:bookmark, user: user, bookmarkable: post) }
it "deletes the existing bookmark" do it "deletes the existing bookmark" do
subject.destroy(bookmark.id) manager.destroy(bookmark.id)
expect(Bookmark.exists?(id: bookmark.id)).to eq(false) expect(Bookmark.exists?(id: bookmark.id)).to eq(false)
end end
context "if the bookmark is the last one bookmarked in the topic" do context "if the bookmark is the last one bookmarked in the topic" do
it "marks the topic user bookmarked column as false" do it "marks the topic user bookmarked column as false" do
TopicUser.create(user: user, topic: post.topic, bookmarked: true) TopicUser.create(user: user, topic: post.topic, bookmarked: true)
subject.destroy(bookmark.id) manager.destroy(bookmark.id)
tu = TopicUser.find_by(user: user) tu = TopicUser.find_by(user: user)
expect(tu.bookmarked).to eq(false) expect(tu.bookmarked).to eq(false)
end end
@ -28,13 +28,13 @@ RSpec.describe BookmarkManager do
context "if the bookmark is belonging to some other user" do context "if the bookmark is belonging to some other user" do
let!(:bookmark) { Fabricate(:bookmark, user: Fabricate(:admin), bookmarkable: post) } let!(:bookmark) { Fabricate(:bookmark, user: Fabricate(:admin), bookmarkable: post) }
it "raises an invalid access error" do it "raises an invalid access error" do
expect { subject.destroy(bookmark.id) }.to raise_error(Discourse::InvalidAccess) expect { manager.destroy(bookmark.id) }.to raise_error(Discourse::InvalidAccess)
end end
end end
context "if the bookmark no longer exists" do context "if the bookmark no longer exists" do
it "raises a not found error" do it "raises a not found error" do
expect { subject.destroy(9999) }.to raise_error(Discourse::NotFound) expect { manager.destroy(9999) }.to raise_error(Discourse::NotFound)
end end
end end
end end
@ -53,7 +53,7 @@ RSpec.describe BookmarkManager do
let(:options) { {} } let(:options) { {} }
def update_bookmark def update_bookmark
subject.update( manager.update(
bookmark_id: bookmark.id, bookmark_id: bookmark.id,
name: new_name, name: new_name,
reminder_at: new_reminder_at, reminder_at: new_reminder_at,
@ -70,7 +70,7 @@ RSpec.describe BookmarkManager do
it "does not reminder_last_sent_at if reminder did not change" do it "does not reminder_last_sent_at if reminder did not change" do
bookmark.update(reminder_last_sent_at: 1.day.ago) bookmark.update(reminder_last_sent_at: 1.day.ago)
subject.update(bookmark_id: bookmark.id, name: new_name, reminder_at: bookmark.reminder_at) manager.update(bookmark_id: bookmark.id, name: new_name, reminder_at: bookmark.reminder_at)
bookmark.reload bookmark.reload
expect(bookmark.reminder_last_sent_at).not_to eq(nil) expect(bookmark.reminder_last_sent_at).not_to eq(nil)
end end
@ -112,20 +112,20 @@ RSpec.describe BookmarkManager do
end end
it "destroys all bookmarks for the topic for the specified user" do it "destroys all bookmarks for the topic for the specified user" do
subject.destroy_for_topic(topic) manager.destroy_for_topic(topic)
expect(Bookmark.for_user_in_topic(user.id, topic.id).length).to eq(0) expect(Bookmark.for_user_in_topic(user.id, topic.id).length).to eq(0)
end end
it "does not destroy any other user's topic bookmarks" do it "does not destroy any other user's topic bookmarks" do
user2 = Fabricate(:user) user2 = Fabricate(:user)
Fabricate(:bookmark, bookmarkable: Fabricate(:post, topic: topic), user: user2) Fabricate(:bookmark, bookmarkable: Fabricate(:post, topic: topic), user: user2)
subject.destroy_for_topic(topic) manager.destroy_for_topic(topic)
expect(Bookmark.for_user_in_topic(user2.id, topic.id).length).to eq(1) expect(Bookmark.for_user_in_topic(user2.id, topic.id).length).to eq(1)
end end
it "updates the topic user bookmarked column to false" do it "updates the topic user bookmarked column to false" do
TopicUser.create(user: user, topic: topic, bookmarked: true) TopicUser.create(user: user, topic: topic, bookmarked: true)
subject.destroy_for_topic(topic) manager.destroy_for_topic(topic)
tu = TopicUser.find_by(user: user) tu = TopicUser.find_by(user: user)
expect(tu.bookmarked).to eq(false) expect(tu.bookmarked).to eq(false)
end end
@ -176,20 +176,20 @@ RSpec.describe BookmarkManager do
it "sets pinned to false if it is true" do it "sets pinned to false if it is true" do
bookmark.update(pinned: true) bookmark.update(pinned: true)
subject.toggle_pin(bookmark_id: bookmark.id) manager.toggle_pin(bookmark_id: bookmark.id)
expect(bookmark.reload.pinned).to eq(false) expect(bookmark.reload.pinned).to eq(false)
end end
it "sets pinned to true if it is false" do it "sets pinned to true if it is false" do
bookmark.update(pinned: false) bookmark.update(pinned: false)
subject.toggle_pin(bookmark_id: bookmark.id) manager.toggle_pin(bookmark_id: bookmark.id)
expect(bookmark.reload.pinned).to eq(true) expect(bookmark.reload.pinned).to eq(true)
end end
context "if the bookmark is belonging to some other user" do context "if the bookmark is belonging to some other user" do
let!(:bookmark) { Fabricate(:bookmark, user: Fabricate(:admin)) } let!(:bookmark) { Fabricate(:bookmark, user: Fabricate(:admin)) }
it "raises an invalid access error" do it "raises an invalid access error" do
expect { subject.toggle_pin(bookmark_id: bookmark.id) }.to raise_error( expect { manager.toggle_pin(bookmark_id: bookmark.id) }.to raise_error(
Discourse::InvalidAccess, Discourse::InvalidAccess,
) )
end end
@ -198,18 +198,18 @@ RSpec.describe BookmarkManager do
context "if the bookmark no longer exists" do context "if the bookmark no longer exists" do
before { bookmark.destroy! } before { bookmark.destroy! }
it "raises a not found error" do it "raises a not found error" do
expect { subject.toggle_pin(bookmark_id: bookmark.id) }.to raise_error(Discourse::NotFound) expect { manager.toggle_pin(bookmark_id: bookmark.id) }.to raise_error(Discourse::NotFound)
end end
end end
end end
describe "#create_for" do describe "#create_for" do
it "allows creating a bookmark for the topic and for the first post" do it "allows creating a bookmark for the topic and for the first post" do
subject.create_for(bookmarkable_id: post.topic_id, bookmarkable_type: "Topic", name: name) manager.create_for(bookmarkable_id: post.topic_id, bookmarkable_type: "Topic", name: name)
bookmark = Bookmark.find_by(user: user, bookmarkable: post.topic) bookmark = Bookmark.find_by(user: user, bookmarkable: post.topic)
expect(bookmark.present?).to eq(true) expect(bookmark.present?).to eq(true)
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name) manager.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name)
bookmark = Bookmark.find_by(user: user, bookmarkable: post) bookmark = Bookmark.find_by(user: user, bookmarkable: post)
expect(bookmark).not_to eq(nil) expect(bookmark).not_to eq(nil)
end end
@ -217,26 +217,26 @@ RSpec.describe BookmarkManager do
it "when topic is deleted it raises invalid access from guardian check" do it "when topic is deleted it raises invalid access from guardian check" do
post.topic.trash! post.topic.trash!
expect { expect {
subject.create_for(bookmarkable_id: post.topic_id, bookmarkable_type: "Topic", name: name) manager.create_for(bookmarkable_id: post.topic_id, bookmarkable_type: "Topic", name: name)
}.to raise_error(Discourse::InvalidAccess) }.to raise_error(Discourse::InvalidAccess)
end end
it "when post is deleted it raises invalid access from guardian check" do it "when post is deleted it raises invalid access from guardian check" do
post.trash! post.trash!
expect do expect do
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name) manager.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name)
end.to raise_error(Discourse::InvalidAccess) end.to raise_error(Discourse::InvalidAccess)
end end
it "adds a validation error when the bookmarkable_type is not registered" do it "adds a validation error when the bookmarkable_type is not registered" do
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "BlahFactory", name: name) manager.create_for(bookmarkable_id: post.id, bookmarkable_type: "BlahFactory", name: name)
expect(subject.errors.full_messages).to include( expect(manager.errors.full_messages).to include(
I18n.t("bookmarks.errors.invalid_bookmarkable", type: "BlahFactory"), I18n.t("bookmarks.errors.invalid_bookmarkable", type: "BlahFactory"),
) )
end end
it "updates the topic user bookmarked column to true if any post is bookmarked" do it "updates the topic user bookmarked column to true if any post is bookmarked" do
subject.create_for( manager.create_for(
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
name: name, name: name,
@ -246,14 +246,14 @@ RSpec.describe BookmarkManager do
expect(tu.bookmarked).to eq(true) expect(tu.bookmarked).to eq(true)
tu.update(bookmarked: false) tu.update(bookmarked: false)
new_post = Fabricate(:post, topic: post.topic) new_post = Fabricate(:post, topic: post.topic)
subject.create_for(bookmarkable_id: new_post.id, bookmarkable_type: "Post") manager.create_for(bookmarkable_id: new_post.id, bookmarkable_type: "Post")
tu.reload tu.reload
expect(tu.bookmarked).to eq(true) expect(tu.bookmarked).to eq(true)
end end
it "sets auto_delete_preference to clear_reminder by default" do it "sets auto_delete_preference to clear_reminder by default" do
bookmark = bookmark =
subject.create_for( manager.create_for(
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
name: name, name: name,
@ -273,7 +273,7 @@ RSpec.describe BookmarkManager do
it "sets auto_delete_preferences to the user's user_option.bookmark_auto_delete_preference" do it "sets auto_delete_preferences to the user's user_option.bookmark_auto_delete_preference" do
bookmark = bookmark =
subject.create_for( manager.create_for(
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
name: name, name: name,
@ -286,7 +286,7 @@ RSpec.describe BookmarkManager do
it "uses the passed in auto_delete_preference option instead of the user's one" do it "uses the passed in auto_delete_preference option instead of the user's one" do
bookmark = bookmark =
subject.create_for( manager.create_for(
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
name: name, name: name,
@ -303,7 +303,7 @@ RSpec.describe BookmarkManager do
context "when a reminder time is provided" do context "when a reminder time is provided" do
it "saves the values correctly" do it "saves the values correctly" do
subject.create_for( manager.create_for(
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
name: name, name: name,
@ -322,7 +322,7 @@ RSpec.describe BookmarkManager do
end end
it "saves any additional options successfully" do it "saves any additional options successfully" do
subject.create_for( manager.create_for(
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
name: name, name: name,
@ -339,8 +339,8 @@ RSpec.describe BookmarkManager do
before { Bookmark.create(bookmarkable: post, user: user) } before { Bookmark.create(bookmarkable: post, user: user) }
it "adds an error to the manager" do it "adds an error to the manager" do
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post") manager.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post")
expect(subject.errors.full_messages).to include( expect(manager.errors.full_messages).to include(
I18n.t("bookmarks.errors.already_bookmarked", type: "Post"), I18n.t("bookmarks.errors.already_bookmarked", type: "Post"),
) )
end end
@ -348,8 +348,8 @@ RSpec.describe BookmarkManager do
context "when the bookmark name is too long" do context "when the bookmark name is too long" do
it "adds an error to the manager" do it "adds an error to the manager" do
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: "test" * 100) manager.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: "test" * 100)
expect(subject.errors.full_messages).to include( expect(manager.errors.full_messages).to include(
"Name is too long (maximum is 100 characters)", "Name is too long (maximum is 100 characters)",
) )
end end
@ -359,13 +359,13 @@ RSpec.describe BookmarkManager do
let(:reminder_at) { 10.days.ago } let(:reminder_at) { 10.days.ago }
it "adds an error to the manager" do it "adds an error to the manager" do
subject.create_for( manager.create_for(
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
name: name, name: name,
reminder_at: reminder_at, reminder_at: reminder_at,
) )
expect(subject.errors.full_messages).to include( expect(manager.errors.full_messages).to include(
I18n.t("bookmarks.errors.cannot_set_past_reminder"), I18n.t("bookmarks.errors.cannot_set_past_reminder"),
) )
end end
@ -375,13 +375,13 @@ RSpec.describe BookmarkManager do
let(:reminder_at) { 11.years.from_now } let(:reminder_at) { 11.years.from_now }
it "adds an error to the manager" do it "adds an error to the manager" do
subject.create_for( manager.create_for(
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
name: name, name: name,
reminder_at: reminder_at, reminder_at: reminder_at,
) )
expect(subject.errors.full_messages).to include( expect(manager.errors.full_messages).to include(
I18n.t("bookmarks.errors.cannot_set_reminder_in_distant_future"), I18n.t("bookmarks.errors.cannot_set_reminder_in_distant_future"),
) )
end end
@ -391,7 +391,7 @@ RSpec.describe BookmarkManager do
before { post.trash! } before { post.trash! }
it "raises an invalid access error" do it "raises an invalid access error" do
expect { expect {
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name) manager.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name)
}.to raise_error(Discourse::InvalidAccess) }.to raise_error(Discourse::InvalidAccess)
end end
end end
@ -400,7 +400,7 @@ RSpec.describe BookmarkManager do
before { post.topic.update(category: Fabricate(:private_category, group: Fabricate(:group))) } before { post.topic.update(category: Fabricate(:private_category, group: Fabricate(:group))) }
it "raises an invalid access error" do it "raises an invalid access error" do
expect { expect {
subject.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name) manager.create_for(bookmarkable_id: post.id, bookmarkable_type: "Post", name: name)
}.to raise_error(Discourse::InvalidAccess) }.to raise_error(Discourse::InvalidAccess)
end end
end end

View File

@ -1,19 +1,20 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe BookmarkReminderNotificationHandler do RSpec.describe BookmarkReminderNotificationHandler do
subject { described_class }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
before { Discourse.redis.flushdb } before { Discourse.redis.flushdb }
describe "#send_notification" do describe "#send_notification" do
subject(:send_notification) { handler.send_notification }
let(:handler) { described_class.new(bookmark) }
let!(:bookmark) do let!(:bookmark) do
Fabricate(:bookmark_next_business_day_reminder, user: user, bookmarkable: Fabricate(:post)) Fabricate(:bookmark_next_business_day_reminder, user: user, bookmarkable: Fabricate(:post))
end end
it "creates a bookmark reminder notification with the correct details" do it "creates a bookmark reminder notification with the correct details" do
subject.new(bookmark).send_notification send_notification
notif = bookmark.user.notifications.last notif = bookmark.user.notifications.last
expect(notif.notification_type).to eq(Notification.types[:bookmark_reminder]) expect(notif.notification_type).to eq(Notification.types[:bookmark_reminder])
expect(notif.topic_id).to eq(bookmark.bookmarkable.topic_id) expect(notif.topic_id).to eq(bookmark.bookmarkable.topic_id)
@ -32,7 +33,7 @@ RSpec.describe BookmarkReminderNotificationHandler do
end end
it "does not send a notification and updates last notification attempt time" do it "does not send a notification and updates last notification attempt time" do
expect { subject.new(bookmark).send_notification }.not_to change { Notification.count } expect { send_notification }.not_to change { Notification.count }
expect(bookmark.reload.reminder_last_sent_at).not_to be_blank expect(bookmark.reload.reminder_last_sent_at).not_to be_blank
end end
end end
@ -46,12 +47,12 @@ RSpec.describe BookmarkReminderNotificationHandler do
end end
it "deletes the bookmark after the reminder gets sent" do it "deletes the bookmark after the reminder gets sent" do
subject.new(bookmark).send_notification send_notification
expect(Bookmark.find_by(id: bookmark.id)).to eq(nil) expect(Bookmark.find_by(id: bookmark.id)).to eq(nil)
end end
it "changes the TopicUser bookmarked column to false" do it "changes the TopicUser bookmarked column to false" do
subject.new(bookmark).send_notification send_notification
expect(TopicUser.find_by(topic: bookmark.bookmarkable.topic, user: user).bookmarked).to eq( expect(TopicUser.find_by(topic: bookmark.bookmarkable.topic, user: user).bookmarked).to eq(
false, false,
) )
@ -67,7 +68,7 @@ RSpec.describe BookmarkReminderNotificationHandler do
end end
it "does not change the TopicUser bookmarked column to false" do it "does not change the TopicUser bookmarked column to false" do
subject.new(bookmark).send_notification send_notification
expect( expect(
TopicUser.find_by(topic: bookmark.bookmarkable.topic, user: user).bookmarked, TopicUser.find_by(topic: bookmark.bookmarkable.topic, user: user).bookmarked,
).to eq(true) ).to eq(true)
@ -82,7 +83,7 @@ RSpec.describe BookmarkReminderNotificationHandler do
end end
it "resets reminder_at after the reminder gets sent" do it "resets reminder_at after the reminder gets sent" do
subject.new(bookmark).send_notification send_notification
expect(Bookmark.find_by(id: bookmark.id).reminder_at).to eq(nil) expect(Bookmark.find_by(id: bookmark.id).reminder_at).to eq(nil)
end end
end end

View File

@ -6,32 +6,32 @@ RSpec.describe CommonPasswords do
end end
describe "#common_password?" do describe "#common_password?" do
before { described_class.stubs(:redis).returns(stub_everything) } subject(:common_password) { described_class.common_password? @password }
subject { described_class.common_password? @password } before { described_class.stubs(:redis).returns(stub_everything) }
it "returns false if password isn't in the common passwords list" do it "returns false if password isn't in the common passwords list" do
described_class.stubs(:password_list).returns(stub_everything(include?: false)) described_class.stubs(:password_list).returns(stub_everything(include?: false))
@password = "uncommonPassword" @password = "uncommonPassword"
expect(subject).to eq(false) expect(common_password).to eq(false)
end end
it "returns false if password is nil" do it "returns false if password is nil" do
described_class.expects(:password_list).never described_class.expects(:password_list).never
@password = nil @password = nil
expect(subject).to eq(false) expect(common_password).to eq(false)
end end
it "returns false if password is blank" do it "returns false if password is blank" do
described_class.expects(:password_list).never described_class.expects(:password_list).never
@password = "" @password = ""
expect(subject).to eq(false) expect(common_password).to eq(false)
end end
it "returns true if password is in the common passwords list" do it "returns true if password is in the common passwords list" do
described_class.stubs(:password_list).returns(stub_everything(include?: true)) described_class.stubs(:password_list).returns(stub_everything(include?: true))
@password = "password" @password = "password"
expect(subject).to eq(true) expect(common_password).to eq(true)
end end
end end

View File

@ -8,7 +8,7 @@ RSpec.describe DiscourseUpdates do
DiscourseUpdates.updated_at = updated_at DiscourseUpdates.updated_at = updated_at
end end
subject { DiscourseUpdates.check_version } subject(:version) { DiscourseUpdates.check_version }
context "when version check was done at the current installed version" do context "when version check was done at the current installed version" do
before { DiscourseUpdates.last_installed_version = Discourse::VERSION::STRING } before { DiscourseUpdates.last_installed_version = Discourse::VERSION::STRING }
@ -19,15 +19,15 @@ RSpec.describe DiscourseUpdates do
before { stub_data(Discourse::VERSION::STRING, 0, false, time) } before { stub_data(Discourse::VERSION::STRING, 0, false, time) }
it "returns all the version fields" do it "returns all the version fields" do
expect(subject.latest_version).to eq(Discourse::VERSION::STRING) expect(version.latest_version).to eq(Discourse::VERSION::STRING)
expect(subject.missing_versions_count).to eq(0) expect(version.missing_versions_count).to eq(0)
expect(subject.critical_updates).to eq(false) expect(version.critical_updates).to eq(false)
expect(subject.installed_version).to eq(Discourse::VERSION::STRING) expect(version.installed_version).to eq(Discourse::VERSION::STRING)
expect(subject.stale_data).to eq(false) expect(version.stale_data).to eq(false)
end end
it "returns the timestamp of the last version check" do it "returns the timestamp of the last version check" do
expect(subject.updated_at).to be_within_one_second_of(time) expect(version.updated_at).to be_within_one_second_of(time)
end end
end end
@ -36,14 +36,14 @@ RSpec.describe DiscourseUpdates do
before { stub_data("0.9.0", 2, false, time) } before { stub_data("0.9.0", 2, false, time) }
it "returns all the version fields" do it "returns all the version fields" do
expect(subject.latest_version).to eq("0.9.0") expect(version.latest_version).to eq("0.9.0")
expect(subject.missing_versions_count).to eq(2) expect(version.missing_versions_count).to eq(2)
expect(subject.critical_updates).to eq(false) expect(version.critical_updates).to eq(false)
expect(subject.installed_version).to eq(Discourse::VERSION::STRING) expect(version.installed_version).to eq(Discourse::VERSION::STRING)
end end
it "returns the timestamp of the last version check" do it "returns the timestamp of the last version check" do
expect(subject.updated_at).to be_within_one_second_of(time) expect(version.updated_at).to be_within_one_second_of(time)
end end
end end
end end
@ -52,22 +52,22 @@ RSpec.describe DiscourseUpdates do
before { stub_data(nil, nil, false, nil) } before { stub_data(nil, nil, false, nil) }
it "returns the installed version" do it "returns the installed version" do
expect(subject.installed_version).to eq(Discourse::VERSION::STRING) expect(version.installed_version).to eq(Discourse::VERSION::STRING)
end end
it "indicates that version check has not been performed" do it "indicates that version check has not been performed" do
expect(subject.updated_at).to eq(nil) expect(version.updated_at).to eq(nil)
expect(subject.stale_data).to eq(true) expect(version.stale_data).to eq(true)
end end
it "does not return latest version info" do it "does not return latest version info" do
expect(subject.latest_version).to eq(nil) expect(version.latest_version).to eq(nil)
expect(subject.missing_versions_count).to eq(nil) expect(version.missing_versions_count).to eq(nil)
expect(subject.critical_updates).to eq(nil) expect(version.critical_updates).to eq(nil)
end end
it "queues a version check" do it "queues a version check" do
expect_enqueued_with(job: :version_check) { subject } expect_enqueued_with(job: :version_check) { version }
end end
end end
@ -76,15 +76,15 @@ RSpec.describe DiscourseUpdates do
context "with old version check data" do context "with old version check data" do
shared_examples "queue version check and report that version is ok" do shared_examples "queue version check and report that version is ok" do
it "queues a version check" do it "queues a version check" do
expect_enqueued_with(job: :version_check) { subject } expect_enqueued_with(job: :version_check) { version }
end end
it "reports 0 missing versions" do it "reports 0 missing versions" do
expect(subject.missing_versions_count).to eq(0) expect(version.missing_versions_count).to eq(0)
end end
it "reports that a version check will be run soon" do it "reports that a version check will be run soon" do
expect(subject.version_check_pending).to eq(true) expect(version.version_check_pending).to eq(true)
end end
end end
@ -105,15 +105,15 @@ RSpec.describe DiscourseUpdates do
shared_examples "when last_installed_version is old" do shared_examples "when last_installed_version is old" do
it "queues a version check" do it "queues a version check" do
expect_enqueued_with(job: :version_check) { subject } expect_enqueued_with(job: :version_check) { version }
end end
it "reports 0 missing versions" do it "reports 0 missing versions" do
expect(subject.missing_versions_count).to eq(0) expect(version.missing_versions_count).to eq(0)
end end
it "reports that a version check will be run soon" do it "reports that a version check will be run soon" do
expect(subject.version_check_pending).to eq(true) expect(version.version_check_pending).to eq(true)
end end
end end

View File

@ -4,9 +4,9 @@ require "email/message_builder"
RSpec.describe Email::MessageBuilder do RSpec.describe Email::MessageBuilder do
let(:to_address) { "jake@adventuretime.ooo" } let(:to_address) { "jake@adventuretime.ooo" }
let(:subject) { "Tree Trunks has made some apple pie!" } let(:email_subject) { "Tree Trunks has made some apple pie!" }
let(:body) { "oh my glob Jake, Tree Trunks just made the tastiest apple pie ever!" } let(:body) { "oh my glob Jake, Tree Trunks just made the tastiest apple pie ever!" }
let(:builder) { Email::MessageBuilder.new(to_address, subject: subject, body: body) } let(:builder) { Email::MessageBuilder.new(to_address, subject: email_subject, body: body) }
let(:build_args) { builder.build_args } let(:build_args) { builder.build_args }
let(:header_args) { builder.header_args } let(:header_args) { builder.header_args }
let(:allow_reply_header) { described_class::ALLOW_REPLY_BY_EMAIL_HEADER } let(:allow_reply_header) { described_class::ALLOW_REPLY_BY_EMAIL_HEADER }
@ -16,7 +16,7 @@ RSpec.describe Email::MessageBuilder do
end end
it "has the subject" do it "has the subject" do
expect(builder.subject).to eq(subject) expect(builder.subject).to eq(email_subject)
end end
it "has the body" do it "has the body" do

View File

@ -6,8 +6,8 @@ describe FinalDestination::SSRFDetector do
SiteSetting.blocked_ip_blocks = "13.134.89.0/24|73.234.19.0/30\n" SiteSetting.blocked_ip_blocks = "13.134.89.0/24|73.234.19.0/30\n"
SiteSetting.allowed_internal_hosts = "awesomesauce.com\n|goodbye.net" SiteSetting.allowed_internal_hosts = "awesomesauce.com\n|goodbye.net"
expect(subject.blocked_ip_blocks).to eq(%w[13.134.89.0/24 73.234.19.0/30]) expect(described_class.blocked_ip_blocks).to eq(%w[13.134.89.0/24 73.234.19.0/30])
expect(subject.allowed_internal_hosts).to eq( expect(described_class.allowed_internal_hosts).to eq(
[ [
"test.localhost", # Discourse.base_url "test.localhost", # Discourse.base_url
"awesomesauce.com", "awesomesauce.com",
@ -20,8 +20,8 @@ describe FinalDestination::SSRFDetector do
SiteSetting.blocked_ip_blocks = "13.134.89.0/24\n73.234.19.0/30\n\n" SiteSetting.blocked_ip_blocks = "13.134.89.0/24\n73.234.19.0/30\n\n"
SiteSetting.allowed_internal_hosts = "awesomesauce.com\n\ngoodbye.net\n\n" SiteSetting.allowed_internal_hosts = "awesomesauce.com\n\ngoodbye.net\n\n"
expect(subject.blocked_ip_blocks).to eq(%w[13.134.89.0/24 73.234.19.0/30]) expect(described_class.blocked_ip_blocks).to eq(%w[13.134.89.0/24 73.234.19.0/30])
expect(subject.allowed_internal_hosts).to eq( expect(described_class.allowed_internal_hosts).to eq(
[ [
"test.localhost", # Discourse.base_url "test.localhost", # Discourse.base_url
"awesomesauce.com", "awesomesauce.com",
@ -32,90 +32,90 @@ describe FinalDestination::SSRFDetector do
it "ignores invalid IP blocks" do it "ignores invalid IP blocks" do
SiteSetting.blocked_ip_blocks = "2001:abc:de::/48|notanip" SiteSetting.blocked_ip_blocks = "2001:abc:de::/48|notanip"
expect(subject.blocked_ip_blocks).to eq(%w[2001:abc:de::/48]) expect(described_class.blocked_ip_blocks).to eq(%w[2001:abc:de::/48])
end end
end end
describe ".ip_allowed?" do describe ".ip_allowed?" do
it "returns false for blocked IPs" do it "returns false for blocked IPs" do
SiteSetting.blocked_ip_blocks = "98.0.0.0/8|78.13.47.0/24|9001:82f3::/32" SiteSetting.blocked_ip_blocks = "98.0.0.0/8|78.13.47.0/24|9001:82f3::/32"
expect(subject.ip_allowed?("98.23.19.111")).to eq(false) expect(described_class.ip_allowed?("98.23.19.111")).to eq(false)
expect(subject.ip_allowed?("9001:82f3:8873::3")).to eq(false) expect(described_class.ip_allowed?("9001:82f3:8873::3")).to eq(false)
end end
%w[0.0.0.0 10.0.0.0 127.0.0.0 172.31.100.31 255.255.255.255 ::1 ::].each do |internal_ip| %w[0.0.0.0 10.0.0.0 127.0.0.0 172.31.100.31 255.255.255.255 ::1 ::].each do |internal_ip|
it "returns false for '#{internal_ip}'" do it "returns false for '#{internal_ip}'" do
expect(subject.ip_allowed?(internal_ip)).to eq(false) expect(described_class.ip_allowed?(internal_ip)).to eq(false)
end end
end end
it "returns false for private IPv4-mapped IPv6 addresses" do it "returns false for private IPv4-mapped IPv6 addresses" do
expect(subject.ip_allowed?("::ffff:172.31.100.31")).to eq(false) expect(described_class.ip_allowed?("::ffff:172.31.100.31")).to eq(false)
expect(subject.ip_allowed?("::ffff:0.0.0.0")).to eq(false) expect(described_class.ip_allowed?("::ffff:0.0.0.0")).to eq(false)
end end
it "returns true for public IPv4-mapped IPv6 addresses" do it "returns true for public IPv4-mapped IPv6 addresses" do
expect(subject.ip_allowed?("::ffff:52.52.167.244")).to eq(true) expect(described_class.ip_allowed?("::ffff:52.52.167.244")).to eq(true)
end end
end end
describe ".host_bypasses_checks?" do describe ".host_bypasses_checks?" do
it "returns true for URLs when allowed_internal_hosts allows the host" do it "returns true for URLs when allowed_internal_hosts allows the host" do
SiteSetting.allowed_internal_hosts = "allowedhost1.com|allowedhost2.com" SiteSetting.allowed_internal_hosts = "allowedhost1.com|allowedhost2.com"
expect(subject.host_bypasses_checks?("allowedhost1.com")).to eq(true) expect(described_class.host_bypasses_checks?("allowedhost1.com")).to eq(true)
expect(subject.host_bypasses_checks?("allowedhost2.com")).to eq(true) expect(described_class.host_bypasses_checks?("allowedhost2.com")).to eq(true)
end end
it "returns false for other hosts" do it "returns false for other hosts" do
expect(subject.host_bypasses_checks?("otherhost.com")).to eq(false) expect(described_class.host_bypasses_checks?("otherhost.com")).to eq(false)
end end
it "returns true for the base uri" do it "returns true for the base uri" do
SiteSetting.force_hostname = "final-test.example.com" SiteSetting.force_hostname = "final-test.example.com"
expect(subject.host_bypasses_checks?("final-test.example.com")).to eq(true) expect(described_class.host_bypasses_checks?("final-test.example.com")).to eq(true)
end end
it "returns true for the S3 CDN url" do it "returns true for the S3 CDN url" do
SiteSetting.enable_s3_uploads = true SiteSetting.enable_s3_uploads = true
SiteSetting.s3_cdn_url = "https://s3.example.com" SiteSetting.s3_cdn_url = "https://s3.example.com"
expect(subject.host_bypasses_checks?("s3.example.com")).to eq(true) expect(described_class.host_bypasses_checks?("s3.example.com")).to eq(true)
end end
it "returns true for the CDN url" do it "returns true for the CDN url" do
GlobalSetting.stubs(:cdn_url).returns("https://cdn.example.com/discourse") GlobalSetting.stubs(:cdn_url).returns("https://cdn.example.com/discourse")
expect(subject.host_bypasses_checks?("cdn.example.com")).to eq(true) expect(described_class.host_bypasses_checks?("cdn.example.com")).to eq(true)
end end
end end
describe ".lookup_and_filter_ips" do describe ".lookup_and_filter_ips" do
it "returns a fake response in tests" do it "returns a fake response in tests" do
expect(subject.lookup_and_filter_ips("example.com")).to eq(["1.2.3.4"]) expect(described_class.lookup_and_filter_ips("example.com")).to eq(["1.2.3.4"])
end end
it "correctly filters private and blocked IPs" do it "correctly filters private and blocked IPs" do
SiteSetting.blocked_ip_blocks = "9.10.11.12/24" SiteSetting.blocked_ip_blocks = "9.10.11.12/24"
subject.stubs(:lookup_ips).returns(%w[127.0.0.1 5.6.7.8 9.10.11.12]) described_class.stubs(:lookup_ips).returns(%w[127.0.0.1 5.6.7.8 9.10.11.12])
expect(subject.lookup_and_filter_ips("example.com")).to eq(["5.6.7.8"]) expect(described_class.lookup_and_filter_ips("example.com")).to eq(["5.6.7.8"])
end end
it "raises an exception if all IPs are blocked" do it "raises an exception if all IPs are blocked" do
subject.stubs(:lookup_ips).returns(["127.0.0.1"]) described_class.stubs(:lookup_ips).returns(["127.0.0.1"])
expect { subject.lookup_and_filter_ips("example.com") }.to raise_error( expect { described_class.lookup_and_filter_ips("example.com") }.to raise_error(
subject::DisallowedIpError, described_class::DisallowedIpError,
) )
end end
it "raises an exception if lookup fails" do it "raises an exception if lookup fails" do
subject.stubs(:lookup_ips).raises(SocketError) described_class.stubs(:lookup_ips).raises(SocketError)
expect { subject.lookup_and_filter_ips("example.com") }.to raise_error( expect { described_class.lookup_and_filter_ips("example.com") }.to raise_error(
subject::LookupFailedError, described_class::LookupFailedError,
) )
end end
it "bypasses filtering for allowlisted hosts" do it "bypasses filtering for allowlisted hosts" do
SiteSetting.allowed_internal_hosts = "example.com" SiteSetting.allowed_internal_hosts = "example.com"
subject.stubs(:lookup_ips).returns(["127.0.0.1"]) described_class.stubs(:lookup_ips).returns(["127.0.0.1"])
expect(subject.lookup_and_filter_ips("example.com")).to eq(["127.0.0.1"]) expect(described_class.lookup_and_filter_ips("example.com")).to eq(["127.0.0.1"])
end end
end end
end end

View File

@ -39,14 +39,14 @@ RSpec.describe Imap::Sync do
describe "no previous sync" do describe "no previous sync" do
let(:from) { "john@free.fr" } let(:from) { "john@free.fr" }
let(:subject) { "Testing email post" } let(:email_subject) { "Testing email post" }
let(:message_id) { "#{SecureRandom.hex}@example.com" } let(:message_id) { "#{SecureRandom.hex}@example.com" }
let(:email) do let(:email) do
EmailFabricator( EmailFabricator(
from: from, from: from,
to: group.email_username, to: group.email_username,
subject: subject, subject: email_subject,
message_id: message_id, message_id: message_id,
) )
end end
@ -80,7 +80,7 @@ RSpec.describe Imap::Sync do
expect(group.imap_last_uid).to eq(100) expect(group.imap_last_uid).to eq(100)
topic = Topic.last topic = Topic.last
expect(topic.title).to eq(subject) expect(topic.title).to eq(email_subject)
expect(topic.user.email).to eq(from) expect(topic.user.email).to eq(from)
expect(topic.tags.pluck(:name)).to contain_exactly("seen", "important", "test-label") expect(topic.tags.pluck(:name)).to contain_exactly("seen", "important", "test-label")
@ -110,7 +110,7 @@ RSpec.describe Imap::Sync do
expect(group.imap_last_uid).to eq(100) expect(group.imap_last_uid).to eq(100)
topic = Topic.last topic = Topic.last
expect(topic.title).to eq(subject) expect(topic.title).to eq(email_subject)
expect(topic.user.email).to eq(from) expect(topic.user.email).to eq(from)
expect(topic.tags).to eq([]) expect(topic.tags).to eq([])
end end
@ -161,7 +161,7 @@ RSpec.describe Imap::Sync do
end end
describe "previous sync" do describe "previous sync" do
let(:subject) { "Testing email post" } let(:email_subject) { "Testing email post" }
let(:first_from) { "john@free.fr" } let(:first_from) { "john@free.fr" }
let(:first_message_id) { SecureRandom.hex } let(:first_message_id) { SecureRandom.hex }
@ -191,7 +191,7 @@ RSpec.describe Imap::Sync do
from: first_from, from: first_from,
to: group.email_username, to: group.email_username,
cc: second_from, cc: second_from,
subject: subject, subject: email_subject,
body: first_body, body: first_body,
), ),
}, },
@ -203,7 +203,7 @@ RSpec.describe Imap::Sync do
}.by(1).and change { IncomingEmail.count }.by(1) }.by(1).and change { IncomingEmail.count }.by(1)
topic = Topic.last topic = Topic.last
expect(topic.title).to eq(subject) expect(topic.title).to eq(email_subject)
expect(GroupArchivedMessage.where(topic_id: topic.id).exists?).to eq(false) expect(GroupArchivedMessage.where(topic_id: topic.id).exists?).to eq(false)
post = Post.where(post_type: Post.types[:regular]).last post = Post.where(post_type: Post.types[:regular]).last
@ -233,7 +233,7 @@ RSpec.describe Imap::Sync do
in_reply_to: first_message_id, in_reply_to: first_message_id,
from: second_from, from: second_from,
to: group.email_username, to: group.email_username,
subject: "Re: #{subject}", subject: "Re: #{email_subject}",
body: second_body, body: second_body,
), ),
}, },
@ -267,7 +267,7 @@ RSpec.describe Imap::Sync do
}.and not_change { IncomingEmail.count } }.and not_change { IncomingEmail.count }
topic = Topic.last topic = Topic.last
expect(topic.title).to eq(subject) expect(topic.title).to eq(email_subject)
expect(GroupArchivedMessage.where(topic_id: topic.id).exists?).to eq(true) expect(GroupArchivedMessage.where(topic_id: topic.id).exists?).to eq(true)
expect(Topic.last.posts.where(post_type: Post.types[:regular]).count).to eq(2) expect(Topic.last.posts.where(post_type: Post.types[:regular]).count).to eq(2)
@ -294,7 +294,7 @@ RSpec.describe Imap::Sync do
from: first_from, from: first_from,
to: group.email_username, to: group.email_username,
cc: second_from, cc: second_from,
subject: subject, subject: email_subject,
body: first_body, body: first_body,
), ),
}, },
@ -389,7 +389,7 @@ RSpec.describe Imap::Sync do
from: first_from, from: first_from,
to: group.email_username, to: group.email_username,
cc: second_from, cc: second_from,
subject: subject, subject: email_subject,
body: first_body, body: first_body,
), ),
}, },
@ -446,7 +446,7 @@ RSpec.describe Imap::Sync do
from: first_from, from: first_from,
to: group.email_username, to: group.email_username,
cc: second_from, cc: second_from,
subject: subject, subject: email_subject,
body: first_body, body: first_body,
), ),
}, },
@ -494,7 +494,7 @@ RSpec.describe Imap::Sync do
end end
describe "invalidated previous sync" do describe "invalidated previous sync" do
let(:subject) { "Testing email post" } let(:email_subject) { "Testing email post" }
let(:first_from) { "john@free.fr" } let(:first_from) { "john@free.fr" }
let(:first_message_id) { SecureRandom.hex } let(:first_message_id) { SecureRandom.hex }
@ -526,7 +526,7 @@ RSpec.describe Imap::Sync do
from: first_from, from: first_from,
to: group.email_username, to: group.email_username,
cc: second_from, cc: second_from,
subject: subject, subject: email_subject,
body: first_body, body: first_body,
), ),
}, },
@ -540,7 +540,7 @@ RSpec.describe Imap::Sync do
in_reply_to: first_message_id, in_reply_to: first_message_id,
from: second_from, from: second_from,
to: group.email_username, to: group.email_username,
subject: "Re: #{subject}", subject: "Re: #{email_subject}",
body: second_body, body: second_body,
), ),
}, },
@ -571,7 +571,7 @@ RSpec.describe Imap::Sync do
from: first_from, from: first_from,
to: group.email_username, to: group.email_username,
cc: second_from, cc: second_from,
subject: subject, subject: email_subject,
body: first_body, body: first_body,
), ),
}, },
@ -585,7 +585,7 @@ RSpec.describe Imap::Sync do
in_reply_to: first_message_id, in_reply_to: first_message_id,
from: second_from, from: second_from,
to: group.email_username, to: group.email_username,
subject: "Re: #{subject}", subject: "Re: #{email_subject}",
body: second_body, body: second_body,
), ),
}, },

View File

@ -5,18 +5,16 @@ RSpec.describe Email::MessageIdService do
fab!(:post) { Fabricate(:post, topic: topic) } fab!(:post) { Fabricate(:post, topic: topic) }
fab!(:second_post) { Fabricate(:post, topic: topic) } fab!(:second_post) { Fabricate(:post, topic: topic) }
subject { described_class }
describe "#generate_or_use_existing" do describe "#generate_or_use_existing" do
it "does not override a post's existing outbound_message_id" do it "does not override a post's existing outbound_message_id" do
post.update!(outbound_message_id: "blah@host.test") post.update!(outbound_message_id: "blah@host.test")
result = subject.generate_or_use_existing(post.id) result = described_class.generate_or_use_existing(post.id)
expect(result).to eq(["<blah@host.test>"]) expect(result).to eq(["<blah@host.test>"])
end end
it "generates an outbound_message_id in the correct format if it's blank for the post" do it "generates an outbound_message_id in the correct format if it's blank for the post" do
post.update!(outbound_message_id: nil) post.update!(outbound_message_id: nil)
result = subject.generate_or_use_existing(post.id) result = described_class.generate_or_use_existing(post.id)
expect(result).to eq(["<discourse/post/#{post.id}@#{Email::MessageIdService.host}>"]) expect(result).to eq(["<discourse/post/#{post.id}@#{Email::MessageIdService.host}>"])
end end
@ -39,7 +37,7 @@ RSpec.describe Email::MessageIdService do
) )
post_bulk4 = Fabricate(:post, topic: topic, created_at: 3.days.ago, outbound_message_id: nil) post_bulk4 = Fabricate(:post, topic: topic, created_at: 3.days.ago, outbound_message_id: nil)
result = result =
subject.generate_or_use_existing( described_class.generate_or_use_existing(
[post_bulk1.id, post_bulk2.id, post_bulk3.id, post_bulk4.id], [post_bulk1.id, post_bulk2.id, post_bulk3.id, post_bulk4.id],
) )
expect(result).to eq( expect(result).to eq(
@ -63,36 +61,43 @@ RSpec.describe Email::MessageIdService do
end end
it "finds a post based only on a post-format message id" do it "finds a post based only on a post-format message id" do
expect(subject.find_post_from_message_ids([post_format_message_id])).to eq(post) expect(described_class.find_post_from_message_ids([post_format_message_id])).to eq(post)
end end
it "finds a post based only on a topic-format message id" do it "finds a post based only on a topic-format message id" do
expect(subject.find_post_from_message_ids([topic_format_message_id])).to eq(post) expect(described_class.find_post_from_message_ids([topic_format_message_id])).to eq(post)
end end
it "finds a post based only on a discourse-format message id" do it "finds a post based only on a discourse-format message id" do
expect(subject.find_post_from_message_ids([discourse_format_message_id])).to eq(post) expect(described_class.find_post_from_message_ids([discourse_format_message_id])).to eq(post)
end end
it "finds a post from the post's outbound_message_id" do it "finds a post from the post's outbound_message_id" do
post.update!(outbound_message_id: subject.message_id_clean(discourse_format_message_id)) post.update!(
expect(subject.find_post_from_message_ids([discourse_format_message_id])).to eq(post) outbound_message_id: described_class.message_id_clean(discourse_format_message_id),
)
expect(described_class.find_post_from_message_ids([discourse_format_message_id])).to eq(post)
end end
it "finds a post from the email log" do it "finds a post from the email log" do
email_log = email_log =
Fabricate(:email_log, message_id: subject.message_id_clean(default_format_message_id)) Fabricate(
expect(subject.find_post_from_message_ids([default_format_message_id])).to eq(email_log.post) :email_log,
message_id: described_class.message_id_clean(default_format_message_id),
)
expect(described_class.find_post_from_message_ids([default_format_message_id])).to eq(
email_log.post,
)
end end
it "finds a post from the incoming email log" do it "finds a post from the incoming email log" do
incoming_email = incoming_email =
Fabricate( Fabricate(
:incoming_email, :incoming_email,
message_id: subject.message_id_clean(gmail_format_message_id), message_id: described_class.message_id_clean(gmail_format_message_id),
post: Fabricate(:post), post: Fabricate(:post),
) )
expect(subject.find_post_from_message_ids([gmail_format_message_id])).to eq( expect(described_class.find_post_from_message_ids([gmail_format_message_id])).to eq(
incoming_email.post, incoming_email.post,
) )
end end
@ -101,16 +106,16 @@ RSpec.describe Email::MessageIdService do
incoming_email = incoming_email =
Fabricate( Fabricate(
:incoming_email, :incoming_email,
message_id: subject.message_id_clean(post_format_message_id), message_id: described_class.message_id_clean(post_format_message_id),
post: Fabricate(:post, created_at: 10.days.ago), post: Fabricate(:post, created_at: 10.days.ago),
) )
expect(subject.find_post_from_message_ids([post_format_message_id])).to eq(post) expect(described_class.find_post_from_message_ids([post_format_message_id])).to eq(post)
end end
end end
describe "#discourse_generated_message_id?" do describe "#discourse_generated_message_id?" do
def check_format(message_id) def check_format(message_id)
subject.discourse_generated_message_id?(message_id) described_class.discourse_generated_message_id?(message_id)
end end
it "works correctly for the different possible formats" do it "works correctly for the different possible formats" do

View File

@ -53,6 +53,16 @@ RSpec.describe Onebox::Engine::GoogleMapsOnebox do
} }
# Register URL redirects # Register URL redirects
# Prevent sleep from wasting our time when we test with strange redirects
subject(:onebox) do
described_class
.send(:allocate)
.tap do |obj|
obj.stubs(:sleep)
obj.send(:initialize, link)
end
end
before do before do
URLS.values.each do |t| URLS.values.each do |t|
status, location = *t[:redirect] status, location = *t[:redirect]
@ -62,27 +72,17 @@ RSpec.describe Onebox::Engine::GoogleMapsOnebox do
end end
end end
# Prevent sleep from wasting our time when we test with strange redirects let(:data) { Onebox::Helpers.symbolize_keys(onebox.send(:data)) }
subject do
described_class
.send(:allocate)
.tap do |obj|
obj.stubs(:sleep)
obj.send(:initialize, link)
end
end
let(:data) { Onebox::Helpers.symbolize_keys(subject.send(:data)) }
let(:link) { |example| URLS[example.metadata[:urltype] || :short][:test] } let(:link) { |example| URLS[example.metadata[:urltype] || :short][:test] }
include_context "an engine", urltype: :short include_context "an engine", urltype: :short
URLS.each do |kind, t| URLS.each do |kind, t|
it "processes #{kind.to_s} url correctly", urltype: kind do it "processes #{kind.to_s} url correctly", urltype: kind do
expect(subject.url).to eq t[:expect] expect(onebox.url).to eq t[:expect]
expect(subject.streetview?).to t[:streetview] ? be_truthy : be_falsey expect(onebox.streetview?).to t[:streetview] ? be_truthy : be_falsey
expect(subject.to_html).to include("<iframe") expect(onebox.to_html).to include("<iframe")
expect(subject.placeholder_html).to include("placeholder-icon map") expect(onebox.placeholder_html).to include("placeholder-icon map")
end end
end end
end end

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Plugin::Instance do RSpec.describe Plugin::Instance do
subject(:plugin_instance) { described_class.new }
after { DiscoursePluginRegistry.reset! } after { DiscoursePluginRegistry.reset! }
describe "find_all" do describe "find_all" do
@ -601,7 +603,7 @@ RSpec.describe Plugin::Instance do
highest_flag_id = ReviewableScore.types.values.max highest_flag_id = ReviewableScore.types.values.max
flag_name = :new_flag flag_name = :new_flag
subject.replace_flags(settings: original_flags) do |settings, next_flag_id| plugin_instance.replace_flags(settings: original_flags) do |settings, next_flag_id|
settings.add(next_flag_id, flag_name) settings.add(next_flag_id, flag_name)
end end
@ -613,7 +615,7 @@ RSpec.describe Plugin::Instance do
highest_flag_id = ReviewableScore.types.values.max highest_flag_id = ReviewableScore.types.values.max
new_score_type = :new_score_type new_score_type = :new_score_type
subject.replace_flags( plugin_instance.replace_flags(
settings: original_flags, settings: original_flags,
score_type_names: [new_score_type], score_type_names: [new_score_type],
) { |settings, next_flag_id| settings.add(next_flag_id, :new_flag) } ) { |settings, next_flag_id| settings.add(next_flag_id, :new_flag) }
@ -629,7 +631,7 @@ RSpec.describe Plugin::Instance do
it "adds a custom api key scope" do it "adds a custom api key scope" do
actions = %w[admin/groups#create] actions = %w[admin/groups#create]
subject.add_api_key_scope(:groups, create: { actions: actions }) plugin_instance.add_api_key_scope(:groups, create: { actions: actions })
expect(ApiKeyScope.scope_mappings.dig(:groups, :create, :actions)).to contain_exactly( expect(ApiKeyScope.scope_mappings.dig(:groups, :create, :actions)).to contain_exactly(
*actions, *actions,

View File

@ -735,20 +735,20 @@ RSpec.describe PostDestroyer do
end end
context "as an admin" do context "as an admin" do
subject { PostDestroyer.new(admin, post).destroy } subject(:destroyer) { PostDestroyer.new(admin, post).destroy }
it "deletes the post" do it "deletes the post" do
subject destroyer
expect(post.deleted_at).to be_present expect(post.deleted_at).to be_present
expect(post.deleted_by).to eq(admin) expect(post.deleted_by).to eq(admin)
end end
it "creates a new user history entry" do it "creates a new user history entry" do
expect { subject }.to change { UserHistory.count }.by(1) expect { destroyer }.to change { UserHistory.count }.by(1)
end end
it "triggers a extensibility event" do it "triggers a extensibility event" do
events = DiscourseEvent.track_events { subject } events = DiscourseEvent.track_events { destroyer }
expect(events[0][:event_name]).to eq(:post_destroyed) expect(events[0][:event_name]).to eq(:post_destroyed)
expect(events[0][:params].first).to eq(post) expect(events[0][:params].first).to eq(post)
@ -768,34 +768,34 @@ RSpec.describe PostDestroyer do
end end
context "as a moderator" do context "as a moderator" do
subject { PostDestroyer.new(moderator, reply).destroy } subject(:destroyer) { PostDestroyer.new(moderator, reply).destroy }
it "deletes the reply" do it "deletes the reply" do
subject destroyer
expect(reply.deleted_at).to be_present expect(reply.deleted_at).to be_present
expect(reply.deleted_by).to eq(moderator) expect(reply.deleted_by).to eq(moderator)
end end
it "doesn't decrement post_count again" do it "doesn't decrement post_count again" do
expect { subject }.to_not change { author.user_stat.post_count } expect { destroyer }.to_not change { author.user_stat.post_count }
end end
end end
context "as an admin" do context "as an admin" do
subject { PostDestroyer.new(admin, reply).destroy } subject(:destroyer) { PostDestroyer.new(admin, reply).destroy }
it "deletes the post" do it "deletes the post" do
subject destroyer
expect(reply.deleted_at).to be_present expect(reply.deleted_at).to be_present
expect(reply.deleted_by).to eq(admin) expect(reply.deleted_by).to eq(admin)
end end
it "doesn't decrement post_count again" do it "doesn't decrement post_count again" do
expect { subject }.to_not change { author.user_stat.post_count } expect { destroyer }.to_not change { author.user_stat.post_count }
end end
it "creates a new user history entry" do it "creates a new user history entry" do
expect { subject }.to change { UserHistory.count }.by(1) expect { destroyer }.to change { UserHistory.count }.by(1)
end end
end end
end end

View File

@ -1,13 +1,13 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe PostJobsEnqueuer do RSpec.describe PostJobsEnqueuer do
subject(:enqueuer) { described_class.new(post, topic, new_topic, opts) }
let!(:post) { Fabricate(:post, topic: topic) } let!(:post) { Fabricate(:post, topic: topic) }
let!(:topic) { Fabricate(:topic) } let!(:topic) { Fabricate(:topic) }
let(:new_topic) { false } let(:new_topic) { false }
let(:opts) { { post_alert_options: {} } } let(:opts) { { post_alert_options: {} } }
subject { described_class.new(post, topic, new_topic, opts) }
context "for regular topics" do context "for regular topics" do
it "enqueues the :post_alert job" do it "enqueues the :post_alert job" do
expect_enqueued_with( expect_enqueued_with(
@ -17,24 +17,24 @@ RSpec.describe PostJobsEnqueuer do
new_record: true, new_record: true,
options: opts[:post_alert_options], options: opts[:post_alert_options],
}, },
) { subject.enqueue_jobs } ) { enqueuer.enqueue_jobs }
end end
it "enqueues the :notify_mailing_list_subscribers job" do it "enqueues the :notify_mailing_list_subscribers job" do
expect_enqueued_with(job: :notify_mailing_list_subscribers, args: { post_id: post.id }) do expect_enqueued_with(job: :notify_mailing_list_subscribers, args: { post_id: post.id }) do
subject.enqueue_jobs enqueuer.enqueue_jobs
end end
end end
it "enqueues the :post_update_topic_tracking_state job" do it "enqueues the :post_update_topic_tracking_state job" do
expect_enqueued_with(job: :post_update_topic_tracking_state, args: { post_id: post.id }) do expect_enqueued_with(job: :post_update_topic_tracking_state, args: { post_id: post.id }) do
subject.enqueue_jobs enqueuer.enqueue_jobs
end end
end end
it "enqueues the :feature_topic_users job" do it "enqueues the :feature_topic_users job" do
expect_enqueued_with(job: :feature_topic_users, args: { topic_id: topic.id }) do expect_enqueued_with(job: :feature_topic_users, args: { topic_id: topic.id }) do
subject.enqueue_jobs enqueuer.enqueue_jobs
end end
end end
@ -44,7 +44,7 @@ RSpec.describe PostJobsEnqueuer do
it "calls the correct topic tracking state class to publish_new" do it "calls the correct topic tracking state class to publish_new" do
TopicTrackingState.expects(:publish_new).with(topic) TopicTrackingState.expects(:publish_new).with(topic)
PrivateMessageTopicTrackingState.expects(:publish_new).never PrivateMessageTopicTrackingState.expects(:publish_new).never
subject.enqueue_jobs enqueuer.enqueue_jobs
end end
end end
end end
@ -54,19 +54,19 @@ RSpec.describe PostJobsEnqueuer do
it "does not enqueue the :notify_mailing_list_subscribers job" do it "does not enqueue the :notify_mailing_list_subscribers job" do
expect_not_enqueued_with(job: :notify_mailing_list_subscribers, args: { post_id: post.id }) do expect_not_enqueued_with(job: :notify_mailing_list_subscribers, args: { post_id: post.id }) do
subject.enqueue_jobs enqueuer.enqueue_jobs
end end
end end
it "enqueues the :post_update_topic_tracking_state job" do it "enqueues the :post_update_topic_tracking_state job" do
expect_enqueued_with(job: :post_update_topic_tracking_state, args: { post_id: post.id }) do expect_enqueued_with(job: :post_update_topic_tracking_state, args: { post_id: post.id }) do
subject.enqueue_jobs enqueuer.enqueue_jobs
end end
end end
it "enqueues the :feature_topic_users job" do it "enqueues the :feature_topic_users job" do
expect_enqueued_with(job: :feature_topic_users, args: { topic_id: topic.id }) do expect_enqueued_with(job: :feature_topic_users, args: { topic_id: topic.id }) do
subject.enqueue_jobs enqueuer.enqueue_jobs
end end
end end
@ -76,7 +76,7 @@ RSpec.describe PostJobsEnqueuer do
it "calls the correct topic tracking state class to publish_new" do it "calls the correct topic tracking state class to publish_new" do
TopicTrackingState.expects(:publish_new).never TopicTrackingState.expects(:publish_new).never
PrivateMessageTopicTrackingState.expects(:publish_new).with(topic) PrivateMessageTopicTrackingState.expects(:publish_new).with(topic)
subject.enqueue_jobs enqueuer.enqueue_jobs
end end
end end
@ -99,7 +99,7 @@ RSpec.describe PostJobsEnqueuer do
args: { args: {
topic_id: topic.id, topic_id: topic.id,
}, },
) { subject.enqueue_jobs } ) { enqueuer.enqueue_jobs }
end end
end end
end end

View File

@ -197,9 +197,9 @@ RSpec.describe PostRevisor do
end end
describe "editing tags" do describe "editing tags" do
fab!(:post) { Fabricate(:post) } subject(:post_revisor) { PostRevisor.new(post) }
subject { PostRevisor.new(post) } fab!(:post) { Fabricate(:post) }
before do before do
Jobs.run_immediately! Jobs.run_immediately!
@ -212,19 +212,21 @@ RSpec.describe PostRevisor do
end end
it "creates notifications" do it "creates notifications" do
expect { subject.revise!(admin, tags: ["new-tag"]) }.to change { Notification.count }.by(1) expect { post_revisor.revise!(admin, tags: ["new-tag"]) }.to change { Notification.count }.by(
1,
)
end end
it "skips notifications if disable_tags_edit_notifications" do it "skips notifications if disable_tags_edit_notifications" do
SiteSetting.disable_tags_edit_notifications = true SiteSetting.disable_tags_edit_notifications = true
expect { subject.revise!(admin, tags: ["new-tag"]) }.not_to change { Notification.count } expect { post_revisor.revise!(admin, tags: ["new-tag"]) }.not_to change { Notification.count }
end end
it "doesn't create a small_action post when create_post_for_category_and_tag_changes is false" do it "doesn't create a small_action post when create_post_for_category_and_tag_changes is false" do
SiteSetting.create_post_for_category_and_tag_changes = false SiteSetting.create_post_for_category_and_tag_changes = false
expect { subject.revise!(admin, tags: ["new-tag"]) }.not_to change { Post.count } expect { post_revisor.revise!(admin, tags: ["new-tag"]) }.not_to change { Post.count }
end end
describe "when `create_post_for_category_and_tag_changes` site setting is enabled" do describe "when `create_post_for_category_and_tag_changes` site setting is enabled" do
@ -236,7 +238,7 @@ RSpec.describe PostRevisor do
it "Creates a small_action post with correct translation when both adding and removing tags" do it "Creates a small_action post with correct translation when both adding and removing tags" do
post.topic.update!(tags: [tag1]) post.topic.update!(tags: [tag1])
expect { subject.revise!(admin, tags: [tag2.name]) }.to change { expect { post_revisor.revise!(admin, tags: [tag2.name]) }.to change {
Post.where(topic_id: post.topic_id, action_code: "tags_changed").count Post.where(topic_id: post.topic_id, action_code: "tags_changed").count
}.by(1) }.by(1)
@ -252,7 +254,7 @@ RSpec.describe PostRevisor do
it "Creates a small_action post with correct translation when adding tags" do it "Creates a small_action post with correct translation when adding tags" do
post.topic.update!(tags: []) post.topic.update!(tags: [])
expect { subject.revise!(admin, tags: [tag1.name]) }.to change { expect { post_revisor.revise!(admin, tags: [tag1.name]) }.to change {
Post.where(topic_id: post.topic_id, action_code: "tags_changed").count Post.where(topic_id: post.topic_id, action_code: "tags_changed").count
}.by(1) }.by(1)
@ -264,7 +266,7 @@ RSpec.describe PostRevisor do
it "Creates a small_action post with correct translation when removing tags" do it "Creates a small_action post with correct translation when removing tags" do
post.topic.update!(tags: [tag1, tag2]) post.topic.update!(tags: [tag1, tag2])
expect { subject.revise!(admin, tags: []) }.to change { expect { post_revisor.revise!(admin, tags: []) }.to change {
Post.where(topic_id: post.topic_id, action_code: "tags_changed").count Post.where(topic_id: post.topic_id, action_code: "tags_changed").count
}.by(1) }.by(1)
@ -277,7 +279,7 @@ RSpec.describe PostRevisor do
current_category = post.topic.category current_category = post.topic.category
category = Fabricate(:category) category = Fabricate(:category)
expect { subject.revise!(admin, category_id: category.id) }.to change { expect { post_revisor.revise!(admin, category_id: category.id) }.to change {
Post.where(topic_id: post.topic_id, action_code: "category_changed").count Post.where(topic_id: post.topic_id, action_code: "category_changed").count
}.by(1) }.by(1)
@ -310,24 +312,24 @@ RSpec.describe PostRevisor do
end end
describe "revise" do describe "revise" do
subject(:post_revisor) { PostRevisor.new(post) }
let(:post) { Fabricate(:post, post_args) } let(:post) { Fabricate(:post, post_args) }
let(:first_version_at) { post.last_version_at } let(:first_version_at) { post.last_version_at }
subject { PostRevisor.new(post) }
it "destroys last revision if edit is undone" do it "destroys last revision if edit is undone" do
old_raw = post.raw old_raw = post.raw
subject.revise!(admin, raw: "new post body", tags: ["new-tag"]) post_revisor.revise!(admin, raw: "new post body", tags: ["new-tag"])
expect(post.topic.reload.tags.map(&:name)).to contain_exactly("new-tag") expect(post.topic.reload.tags.map(&:name)).to contain_exactly("new-tag")
expect(post.post_revisions.reload.size).to eq(1) expect(post.post_revisions.reload.size).to eq(1)
expect(subject.raw_changed?).to eq(true) expect(post_revisor.raw_changed?).to eq(true)
subject.revise!(admin, raw: old_raw, tags: []) post_revisor.revise!(admin, raw: old_raw, tags: [])
expect(post.topic.reload.tags.map(&:name)).to be_empty expect(post.topic.reload.tags.map(&:name)).to be_empty
expect(post.post_revisions.reload.size).to eq(0) expect(post.post_revisions.reload.size).to eq(0)
subject.revise!(admin, raw: "next post body", tags: ["new-tag"]) post_revisor.revise!(admin, raw: "next post body", tags: ["new-tag"])
expect(post.topic.reload.tags.map(&:name)).to contain_exactly("new-tag") expect(post.topic.reload.tags.map(&:name)).to contain_exactly("new-tag")
expect(post.post_revisions.reload.size).to eq(1) expect(post.post_revisions.reload.size).to eq(1)
end end
@ -335,7 +337,7 @@ RSpec.describe PostRevisor do
describe "with the same body" do describe "with the same body" do
it "doesn't change version" do it "doesn't change version" do
expect { expect {
expect(subject.revise!(post.user, raw: post.raw)).to eq(false) expect(post_revisor.revise!(post.user, raw: post.raw)).to eq(false)
post.reload post.reload
}.not_to change(post, :version) }.not_to change(post, :version)
end end
@ -344,7 +346,7 @@ RSpec.describe PostRevisor do
describe "with nil raw contents" do describe "with nil raw contents" do
it "doesn't change version" do it "doesn't change version" do
expect { expect {
expect(subject.revise!(post.user, raw: nil)).to eq(false) expect(post_revisor.revise!(post.user, raw: nil)).to eq(false)
post.reload post.reload
}.not_to change(post, :version) }.not_to change(post, :version)
end end
@ -354,7 +356,7 @@ RSpec.describe PostRevisor do
before { topic.update!(slow_mode_seconds: 1000) } before { topic.update!(slow_mode_seconds: 1000) }
it "regular edits are not allowed by default" do it "regular edits are not allowed by default" do
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "updated body" }, { raw: "updated body" },
revised_at: post.updated_at + 1000.minutes, revised_at: post.updated_at + 1000.minutes,
@ -368,7 +370,7 @@ RSpec.describe PostRevisor do
it "grace period editing is allowed" do it "grace period editing is allowed" do
SiteSetting.editing_grace_period = 1.minute SiteSetting.editing_grace_period = 1.minute
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "updated body" }, { raw: "updated body" },
revised_at: post.updated_at + 10.seconds, revised_at: post.updated_at + 10.seconds,
@ -381,7 +383,7 @@ RSpec.describe PostRevisor do
it "regular edits are allowed if it was turned on in settings" do it "regular edits are allowed if it was turned on in settings" do
SiteSetting.slow_mode_prevents_editing = false SiteSetting.slow_mode_prevents_editing = false
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "updated body" }, { raw: "updated body" },
revised_at: post.updated_at + 10.minutes, revised_at: post.updated_at + 10.minutes,
@ -393,7 +395,11 @@ RSpec.describe PostRevisor do
it "staff is allowed to edit posts even if the topic is in slow mode" do it "staff is allowed to edit posts even if the topic is in slow mode" do
admin = Fabricate(:admin) admin = Fabricate(:admin)
subject.revise!(admin, { raw: "updated body" }, revised_at: post.updated_at + 10.minutes) post_revisor.revise!(
admin,
{ raw: "updated body" },
revised_at: post.updated_at + 10.minutes,
)
post.reload post.reload
expect(post.errors).to be_empty expect(post.errors).to be_empty
@ -404,7 +410,7 @@ RSpec.describe PostRevisor do
it "correctly applies edits" do it "correctly applies edits" do
SiteSetting.editing_grace_period = 1.minute SiteSetting.editing_grace_period = 1.minute
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "updated body" }, { raw: "updated body" },
revised_at: post.updated_at + 10.seconds, revised_at: post.updated_at + 10.seconds,
@ -415,7 +421,7 @@ RSpec.describe PostRevisor do
expect(post.public_version).to eq(1) expect(post.public_version).to eq(1)
expect(post.revisions.size).to eq(0) expect(post.revisions.size).to eq(0)
expect(post.last_version_at).to eq_time(first_version_at) expect(post.last_version_at).to eq_time(first_version_at)
expect(subject.category_changed).to be_blank expect(post_revisor.category_changed).to be_blank
end end
it "does create a new version if a large diff happens" do it "does create a new version if a large diff happens" do
@ -486,13 +492,13 @@ RSpec.describe PostRevisor do
SiteSetting.editing_grace_period_max_diff = 100 SiteSetting.editing_grace_period_max_diff = 100
# making a revision # making a revision
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "updated body" }, { raw: "updated body" },
revised_at: post.updated_at + SiteSetting.editing_grace_period + 1.seconds, revised_at: post.updated_at + SiteSetting.editing_grace_period + 1.seconds,
) )
# "roll back" # "roll back"
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "Hello world" }, { raw: "Hello world" },
revised_at: post.updated_at + SiteSetting.editing_grace_period + 2.seconds, revised_at: post.updated_at + SiteSetting.editing_grace_period + 2.seconds,
@ -507,7 +513,7 @@ RSpec.describe PostRevisor do
it "should bump the topic" do it "should bump the topic" do
expect { expect {
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "updated body" }, { raw: "updated body" },
revised_at: post.updated_at + SiteSetting.editing_grace_period + 1.seconds, revised_at: post.updated_at + SiteSetting.editing_grace_period + 1.seconds,
@ -520,7 +526,7 @@ RSpec.describe PostRevisor do
post_from_topic_with_no_category = Fabricate(:post, topic: topic_with_no_category) post_from_topic_with_no_category = Fabricate(:post, topic: topic_with_no_category)
expect { expect {
result = result =
subject.revise!( post_revisor.revise!(
Fabricate(:admin), Fabricate(:admin),
raw: post_from_topic_with_no_category.raw, raw: post_from_topic_with_no_category.raw,
tags: ["foo"], tags: ["foo"],
@ -533,7 +539,7 @@ RSpec.describe PostRevisor do
TopicUser.create!(topic: post.topic, user: post.user, notification_level: 0) TopicUser.create!(topic: post.topic, user: post.user, notification_level: 0)
messages = messages =
MessageBus.track_publish("/latest") do MessageBus.track_publish("/latest") do
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "updated body" }, { raw: "updated body" },
revised_at: post.updated_at + SiteSetting.editing_grace_period + 1.seconds, revised_at: post.updated_at + SiteSetting.editing_grace_period + 1.seconds,
@ -632,12 +638,12 @@ RSpec.describe PostRevisor do
before do before do
SiteSetting.editing_grace_period = 1.minute SiteSetting.editing_grace_period = 1.minute
subject.revise!(post.user, { raw: "updated body" }, revised_at: revised_at) post_revisor.revise!(post.user, { raw: "updated body" }, revised_at: revised_at)
post.reload post.reload
end end
it "doesn't update a category" do it "doesn't update a category" do
expect(subject.category_changed).to be_blank expect(post_revisor.category_changed).to be_blank
end end
it "updates the versions" do it "updates the versions" do
@ -655,7 +661,11 @@ RSpec.describe PostRevisor do
describe "new edit window" do describe "new edit window" do
before do before do
subject.revise!(post.user, { raw: "yet another updated body" }, revised_at: revised_at) post_revisor.revise!(
post.user,
{ raw: "yet another updated body" },
revised_at: revised_at,
)
post.reload post.reload
end end
@ -669,14 +679,14 @@ RSpec.describe PostRevisor do
end end
it "doesn't update a category" do it "doesn't update a category" do
expect(subject.category_changed).to be_blank expect(post_revisor.category_changed).to be_blank
end end
context "after second window" do context "after second window" do
let!(:new_revised_at) { revised_at + 2.minutes } let!(:new_revised_at) { revised_at + 2.minutes }
before do before do
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ raw: "yet another, another updated body" }, { raw: "yet another, another updated body" },
revised_at: new_revised_at, revised_at: new_revised_at,
@ -711,12 +721,12 @@ RSpec.describe PostRevisor do
context "with one paragraph description" do context "with one paragraph description" do
before do before do
subject.revise!(post.user, raw: new_description) post_revisor.revise!(post.user, raw: new_description)
category.reload category.reload
end end
it "returns the changed category info" do it "returns the changed category info" do
expect(subject.category_changed).to eq(category) expect(post_revisor.category_changed).to eq(category)
end end
it "updates the description of the category" do it "updates the description of the category" do
@ -726,12 +736,12 @@ RSpec.describe PostRevisor do
context "with multiple paragraph description" do context "with multiple paragraph description" do
before do before do
subject.revise!(post.user, raw: "#{new_description}\n\nOther content goes here.") post_revisor.revise!(post.user, raw: "#{new_description}\n\nOther content goes here.")
category.reload category.reload
end end
it "returns the changed category info" do it "returns the changed category info" do
expect(subject.category_changed).to eq(category) expect(post_revisor.category_changed).to eq(category)
end end
it "updates the description of the category" do it "updates the description of the category" do
@ -741,7 +751,7 @@ RSpec.describe PostRevisor do
context "with invalid description without paragraphs" do context "with invalid description without paragraphs" do
before do before do
subject.revise!(post.user, raw: "# This is a title") post_revisor.revise!(post.user, raw: "# This is a title")
category.reload category.reload
end end
@ -760,7 +770,7 @@ RSpec.describe PostRevisor do
context "when updating back to the original paragraph" do context "when updating back to the original paragraph" do
before do before do
category.update_column(:description, "this is my description") category.update_column(:description, "this is my description")
subject.revise!(post.user, raw: Category.post_template) post_revisor.revise!(post.user, raw: Category.post_template)
category.reload category.reload
end end
@ -769,7 +779,7 @@ RSpec.describe PostRevisor do
end end
it "returns the changed category info" do it "returns the changed category info" do
expect(subject.category_changed).to eq(category) expect(post_revisor.category_changed).to eq(category)
end end
end end
end end
@ -786,16 +796,16 @@ RSpec.describe PostRevisor do
it "triggers a rate limiter" do it "triggers a rate limiter" do
EditRateLimiter.any_instance.expects(:performed!) EditRateLimiter.any_instance.expects(:performed!)
subject.revise!(changed_by, raw: "updated body") post_revisor.revise!(changed_by, raw: "updated body")
end end
it "raises error when a user gets rate limited" do it "raises error when a user gets rate limited" do
SiteSetting.max_edits_per_day = 1 SiteSetting.max_edits_per_day = 1
user = Fabricate(:user, trust_level: 1) user = Fabricate(:user, trust_level: 1)
subject.revise!(user, raw: "body (edited)") post_revisor.revise!(user, raw: "body (edited)")
expect do subject.revise!(user, raw: "body (edited twice) ") end.to raise_error( expect do post_revisor.revise!(user, raw: "body (edited twice) ") end.to raise_error(
RateLimiter::LimitExceeded, RateLimiter::LimitExceeded,
) )
end end
@ -807,26 +817,26 @@ RSpec.describe PostRevisor do
SiteSetting.tl4_additional_edits_per_day_multiplier = 4 SiteSetting.tl4_additional_edits_per_day_multiplier = 4
user = Fabricate(:user, trust_level: 2) user = Fabricate(:user, trust_level: 2)
expect { subject.revise!(user, raw: "body (edited)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited)") }.to_not raise_error
expect { subject.revise!(user, raw: "body (edited twice)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited twice)") }.to_not raise_error
expect do subject.revise!(user, raw: "body (edited three times) ") end.to raise_error( expect do post_revisor.revise!(user, raw: "body (edited three times) ") end.to raise_error(
RateLimiter::LimitExceeded, RateLimiter::LimitExceeded,
) )
user = Fabricate(:user, trust_level: 3) user = Fabricate(:user, trust_level: 3)
expect { subject.revise!(user, raw: "body (edited)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited)") }.to_not raise_error
expect { subject.revise!(user, raw: "body (edited twice)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited twice)") }.to_not raise_error
expect { subject.revise!(user, raw: "body (edited three times)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited three times)") }.to_not raise_error
expect do subject.revise!(user, raw: "body (edited four times) ") end.to raise_error( expect do post_revisor.revise!(user, raw: "body (edited four times) ") end.to raise_error(
RateLimiter::LimitExceeded, RateLimiter::LimitExceeded,
) )
user = Fabricate(:user, trust_level: 4) user = Fabricate(:user, trust_level: 4)
expect { subject.revise!(user, raw: "body (edited)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited)") }.to_not raise_error
expect { subject.revise!(user, raw: "body (edited twice)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited twice)") }.to_not raise_error
expect { subject.revise!(user, raw: "body (edited three times)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited three times)") }.to_not raise_error
expect { subject.revise!(user, raw: "body (edited four times)") }.to_not raise_error expect { post_revisor.revise!(user, raw: "body (edited four times)") }.to_not raise_error
expect do subject.revise!(user, raw: "body (edited five times) ") end.to raise_error( expect do post_revisor.revise!(user, raw: "body (edited five times) ") end.to raise_error(
RateLimiter::LimitExceeded, RateLimiter::LimitExceeded,
) )
end end
@ -839,7 +849,7 @@ RSpec.describe PostRevisor do
SiteSetting.newuser_max_embedded_media = 0 SiteSetting.newuser_max_embedded_media = 0
url = "http://i.imgur.com/wfn7rgU.jpg" url = "http://i.imgur.com/wfn7rgU.jpg"
Oneboxer.stubs(:onebox).with(url, anything).returns("<img src='#{url}'>") Oneboxer.stubs(:onebox).with(url, anything).returns("<img src='#{url}'>")
subject.revise!(changed_by, raw: "So, post them here!\n#{url}") post_revisor.revise!(changed_by, raw: "So, post them here!\n#{url}")
end end
it "allows an admin to insert images into a new user's post" do it "allows an admin to insert images into a new user's post" do
@ -856,7 +866,7 @@ RSpec.describe PostRevisor do
SiteSetting.newuser_max_embedded_media = 0 SiteSetting.newuser_max_embedded_media = 0
url = "http://i.imgur.com/FGg7Vzu.gif" url = "http://i.imgur.com/FGg7Vzu.gif"
Oneboxer.stubs(:cached_onebox).with(url, anything).returns("<img src='#{url}'>") Oneboxer.stubs(:cached_onebox).with(url, anything).returns("<img src='#{url}'>")
subject.revise!(post.user, raw: "So, post them here!\n#{url}") post_revisor.revise!(post.user, raw: "So, post them here!\n#{url}")
end end
it "doesn't allow images to be inserted" do it "doesn't allow images to be inserted" do
@ -868,7 +878,7 @@ RSpec.describe PostRevisor do
before { SiteSetting.editing_grace_period_max_diff = 1000 } before { SiteSetting.editing_grace_period_max_diff = 1000 }
fab!(:changed_by) { coding_horror } fab!(:changed_by) { coding_horror }
let!(:result) { subject.revise!(changed_by, raw: "lets update the body. Здравствуйте") } let!(:result) { post_revisor.revise!(changed_by, raw: "lets update the body. Здравствуйте") }
it "correctly updates raw" do it "correctly updates raw" do
expect(result).to eq(true) expect(result).to eq(true)
@ -886,7 +896,7 @@ RSpec.describe PostRevisor do
end end
it "increases the post_edits stat count" do it "increases the post_edits stat count" do
expect do subject.revise!(post.user, { raw: "This is a new revision" }) end.to change { expect do post_revisor.revise!(post.user, { raw: "This is a new revision" }) end.to change {
post.user.user_stat.post_edits_count.to_i post.user.user_stat.post_edits_count.to_i
}.by(1) }.by(1)
end end
@ -894,7 +904,7 @@ RSpec.describe PostRevisor do
context "when second poster posts again quickly" do context "when second poster posts again quickly" do
it "is a grace period edit, because the second poster posted again quickly" do it "is a grace period edit, because the second poster posted again quickly" do
SiteSetting.editing_grace_period = 1.minute SiteSetting.editing_grace_period = 1.minute
subject.revise!( post_revisor.revise!(
changed_by, changed_by,
{ raw: "yet another updated body" }, { raw: "yet another updated body" },
revised_at: post.updated_at + 10.seconds, revised_at: post.updated_at + 10.seconds,
@ -909,7 +919,7 @@ RSpec.describe PostRevisor do
context "when passing skip_revision as true" do context "when passing skip_revision as true" do
before do before do
SiteSetting.editing_grace_period = 1.minute SiteSetting.editing_grace_period = 1.minute
subject.revise!( post_revisor.revise!(
changed_by, changed_by,
{ raw: "yet another updated body" }, { raw: "yet another updated body" },
revised_at: post.updated_at + 10.hours, revised_at: post.updated_at + 10.hours,
@ -928,7 +938,7 @@ RSpec.describe PostRevisor do
context "when editing the before_edit_post event signature" do context "when editing the before_edit_post event signature" do
it "contains post and params" do it "contains post and params" do
params = { raw: "body (edited)" } params = { raw: "body (edited)" }
events = DiscourseEvent.track_events { subject.revise!(user, params) } events = DiscourseEvent.track_events { post_revisor.revise!(user, params) }
expect(events).to include(event_name: :before_edit_post, params: [post, params]) expect(events).to include(event_name: :before_edit_post, params: [post, params])
end end
end end
@ -955,7 +965,7 @@ RSpec.describe PostRevisor do
end end
it "doesn't strip starting whitespaces" do it "doesn't strip starting whitespaces" do
subject.revise!(post.user, raw: " <-- whitespaces --> ") post_revisor.revise!(post.user, raw: " <-- whitespaces --> ")
post.reload post.reload
expect(post.raw).to eq(" <-- whitespaces -->") expect(post.raw).to eq(" <-- whitespaces -->")
end end
@ -963,20 +973,24 @@ RSpec.describe PostRevisor do
it "revises and tracks changes of topic titles" do it "revises and tracks changes of topic titles" do
new_title = "New topic title" new_title = "New topic title"
result = result =
subject.revise!(post.user, { title: new_title }, revised_at: post.updated_at + 10.minutes) post_revisor.revise!(
post.user,
{ title: new_title },
revised_at: post.updated_at + 10.minutes,
)
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post.topic.title).to eq(new_title) expect(post.topic.title).to eq(new_title)
expect(post.revisions.first.modifications["title"][1]).to eq(new_title) expect(post.revisions.first.modifications["title"][1]).to eq(new_title)
expect(subject.topic_title_changed?).to eq(true) expect(post_revisor.topic_title_changed?).to eq(true)
expect(subject.raw_changed?).to eq(false) expect(post_revisor.raw_changed?).to eq(false)
end end
it "revises and tracks changes of topic archetypes" do it "revises and tracks changes of topic archetypes" do
new_archetype = Archetype.banner new_archetype = Archetype.banner
result = result =
subject.revise!( post_revisor.revise!(
post.user, post.user,
{ archetype: new_archetype }, { archetype: new_archetype },
revised_at: post.updated_at + 10.minutes, revised_at: post.updated_at + 10.minutes,
@ -986,21 +1000,21 @@ RSpec.describe PostRevisor do
post.reload post.reload
expect(post.topic.archetype).to eq(new_archetype) expect(post.topic.archetype).to eq(new_archetype)
expect(post.revisions.first.modifications["archetype"][1]).to eq(new_archetype) expect(post.revisions.first.modifications["archetype"][1]).to eq(new_archetype)
expect(subject.raw_changed?).to eq(false) expect(post_revisor.raw_changed?).to eq(false)
end end
it "revises and tracks changes of topic tags" do it "revises and tracks changes of topic tags" do
subject.revise!(admin, tags: ["new-tag"]) post_revisor.revise!(admin, tags: ["new-tag"])
expect(post.post_revisions.last.modifications).to eq("tags" => [[], ["new-tag"]]) expect(post.post_revisions.last.modifications).to eq("tags" => [[], ["new-tag"]])
expect(subject.raw_changed?).to eq(false) expect(post_revisor.raw_changed?).to eq(false)
subject.revise!(admin, tags: %w[new-tag new-tag-2]) post_revisor.revise!(admin, tags: %w[new-tag new-tag-2])
expect(post.post_revisions.last.modifications).to eq("tags" => [[], %w[new-tag new-tag-2]]) expect(post.post_revisions.last.modifications).to eq("tags" => [[], %w[new-tag new-tag-2]])
expect(subject.raw_changed?).to eq(false) expect(post_revisor.raw_changed?).to eq(false)
subject.revise!(admin, tags: ["new-tag-3"]) post_revisor.revise!(admin, tags: ["new-tag-3"])
expect(post.post_revisions.last.modifications).to eq("tags" => [[], ["new-tag-3"]]) expect(post.post_revisions.last.modifications).to eq("tags" => [[], ["new-tag-3"]])
expect(subject.raw_changed?).to eq(false) expect(post_revisor.raw_changed?).to eq(false)
end end
describe "#publish_changes" do describe "#publish_changes" do
@ -1023,14 +1037,14 @@ RSpec.describe PostRevisor do
context "when logging staff edits" do context "when logging staff edits" do
it "doesn't log when a regular user revises a post" do it "doesn't log when a regular user revises a post" do
subject.revise!(post.user, raw: "lets totally update the body") post_revisor.revise!(post.user, raw: "lets totally update the body")
log = log =
UserHistory.where(acting_user_id: post.user.id, action: UserHistory.actions[:post_edit]) UserHistory.where(acting_user_id: post.user.id, action: UserHistory.actions[:post_edit])
expect(log).to be_blank expect(log).to be_blank
end end
it "logs an edit when a staff member revises a post" do it "logs an edit when a staff member revises a post" do
subject.revise!(moderator, raw: "lets totally update the body") post_revisor.revise!(moderator, raw: "lets totally update the body")
log = log =
UserHistory.where( UserHistory.where(
acting_user_id: moderator.id, acting_user_id: moderator.id,
@ -1041,7 +1055,11 @@ RSpec.describe PostRevisor do
end end
it "doesn't log an edit when skip_staff_log is true" do it "doesn't log an edit when skip_staff_log is true" do
subject.revise!(moderator, { raw: "lets totally update the body" }, skip_staff_log: true) post_revisor.revise!(
moderator,
{ raw: "lets totally update the body" },
skip_staff_log: true,
)
log = log =
UserHistory.where( UserHistory.where(
acting_user_id: moderator.id, acting_user_id: moderator.id,
@ -1095,7 +1113,7 @@ RSpec.describe PostRevisor do
before { SiteSetting.staff_edit_locks_post = false } before { SiteSetting.staff_edit_locks_post = false }
it "does not lock the post when revised" do it "does not lock the post when revised" do
result = subject.revise!(moderator, raw: "lets totally update the body") result = post_revisor.revise!(moderator, raw: "lets totally update the body")
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post).not_to be_locked expect(post).not_to be_locked
@ -1106,7 +1124,7 @@ RSpec.describe PostRevisor do
before { SiteSetting.staff_edit_locks_post = true } before { SiteSetting.staff_edit_locks_post = true }
it "locks the post when revised by staff" do it "locks the post when revised by staff" do
result = subject.revise!(moderator, raw: "lets totally update the body") result = post_revisor.revise!(moderator, raw: "lets totally update the body")
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post).to be_locked expect(post).to be_locked
@ -1114,14 +1132,14 @@ RSpec.describe PostRevisor do
it "doesn't lock the wiki posts" do it "doesn't lock the wiki posts" do
post.wiki = true post.wiki = true
result = subject.revise!(moderator, raw: "some new raw content") result = post_revisor.revise!(moderator, raw: "some new raw content")
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post).not_to be_locked expect(post).not_to be_locked
end end
it "doesn't lock the post when the raw did not change" do it "doesn't lock the post when the raw did not change" do
result = subject.revise!(moderator, title: "New topic title, cool!") result = post_revisor.revise!(moderator, title: "New topic title, cool!")
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post.topic.title).to eq("New topic title, cool!") expect(post.topic.title).to eq("New topic title, cool!")
@ -1129,14 +1147,15 @@ RSpec.describe PostRevisor do
end end
it "doesn't lock the post when revised by a regular user" do it "doesn't lock the post when revised by a regular user" do
result = subject.revise!(user, raw: "lets totally update the body") result = post_revisor.revise!(user, raw: "lets totally update the body")
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post).not_to be_locked expect(post).not_to be_locked
end end
it "doesn't lock the post when revised by system user" do it "doesn't lock the post when revised by system user" do
result = subject.revise!(Discourse.system_user, raw: "I usually replace hotlinked images") result =
post_revisor.revise!(Discourse.system_user, raw: "I usually replace hotlinked images")
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post).not_to be_locked expect(post).not_to be_locked
@ -1161,13 +1180,16 @@ RSpec.describe PostRevisor do
it "generates a notification for a mention" do it "generates a notification for a mention" do
expect { expect {
subject.revise!(user, raw: "Random user is mentioning @#{mentioned_user.username_lower}") post_revisor.revise!(
user,
raw: "Random user is mentioning @#{mentioned_user.username_lower}",
)
}.to change { Notification.where(notification_type: Notification.types[:mentioned]).count } }.to change { Notification.where(notification_type: Notification.types[:mentioned]).count }
end end
it "never generates a notification for a mention when the System user revise a post" do it "never generates a notification for a mention when the System user revise a post" do
expect { expect {
subject.revise!( post_revisor.revise!(
Discourse.system_user, Discourse.system_user,
raw: "System user is mentioning @#{mentioned_user.username_lower}", raw: "System user is mentioning @#{mentioned_user.username_lower}",
) )
@ -1183,7 +1205,11 @@ RSpec.describe PostRevisor do
it "doesn't add the tags" do it "doesn't add the tags" do
result = result =
subject.revise!(user, raw: "lets totally update the body", tags: %w[totally update]) post_revisor.revise!(
user,
raw: "lets totally update the body",
tags: %w[totally update],
)
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post.topic.tags.size).to eq(0) expect(post.topic.tags.size).to eq(0)
@ -1202,7 +1228,11 @@ RSpec.describe PostRevisor do
it "can create all tags if none exist" do it "can create all tags if none exist" do
expect { expect {
@result = @result =
subject.revise!(user, raw: "lets totally update the body", tags: %w[totally update]) post_revisor.revise!(
user,
raw: "lets totally update the body",
tags: %w[totally update],
)
}.to change { Tag.count }.by(2) }.to change { Tag.count }.by(2)
expect(@result).to eq(true) expect(@result).to eq(true)
post.reload post.reload
@ -1213,7 +1243,11 @@ RSpec.describe PostRevisor do
Fabricate(:tag, name: "totally") Fabricate(:tag, name: "totally")
expect { expect {
@result = @result =
subject.revise!(user, raw: "lets totally update the body", tags: %w[totally update]) post_revisor.revise!(
user,
raw: "lets totally update the body",
tags: %w[totally update],
)
}.to change { Tag.count }.by(1) }.to change { Tag.count }.by(1)
expect(@result).to eq(true) expect(@result).to eq(true)
post.reload post.reload
@ -1222,7 +1256,7 @@ RSpec.describe PostRevisor do
it "can remove all tags" do it "can remove all tags" do
topic.tags = [Fabricate(:tag, name: "super"), Fabricate(:tag, name: "stuff")] topic.tags = [Fabricate(:tag, name: "super"), Fabricate(:tag, name: "stuff")]
result = subject.revise!(user, raw: "lets totally update the body", tags: []) result = post_revisor.revise!(user, raw: "lets totally update the body", tags: [])
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post.topic.tags.size).to eq(0) expect(post.topic.tags.size).to eq(0)
@ -1231,7 +1265,11 @@ RSpec.describe PostRevisor do
it "can't add staff-only tags" do it "can't add staff-only tags" do
create_staff_only_tags(["important"]) create_staff_only_tags(["important"])
result = result =
subject.revise!(user, raw: "lets totally update the body", tags: %w[important stuff]) post_revisor.revise!(
user,
raw: "lets totally update the body",
tags: %w[important stuff],
)
expect(result).to eq(false) expect(result).to eq(false)
expect(post.topic.errors.present?).to eq(true) expect(post.topic.errors.present?).to eq(true)
end end
@ -1239,7 +1277,11 @@ RSpec.describe PostRevisor do
it "staff can add staff-only tags" do it "staff can add staff-only tags" do
create_staff_only_tags(["important"]) create_staff_only_tags(["important"])
result = result =
subject.revise!(admin, raw: "lets totally update the body", tags: %w[important stuff]) post_revisor.revise!(
admin,
raw: "lets totally update the body",
tags: %w[important stuff],
)
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post.topic.tags.map(&:name).sort).to eq(%w[important stuff]) expect(post.topic.tags.map(&:name).sort).to eq(%w[important stuff])
@ -1250,7 +1292,7 @@ RSpec.describe PostRevisor do
events = events =
DiscourseEvent.track_events do DiscourseEvent.track_events do
subject.revise!(user, raw: "lets totally update the body", tags: []) post_revisor.revise!(user, raw: "lets totally update the body", tags: [])
end end
event = events.find { |e| e[:event_name] == :post_edited } event = events.find { |e| e[:event_name] == :post_edited }
@ -1273,7 +1315,8 @@ RSpec.describe PostRevisor do
end end
it "staff-only tags can't be removed" do it "staff-only tags can't be removed" do
result = subject.revise!(user, raw: "lets totally update the body", tags: ["stuff"]) result =
post_revisor.revise!(user, raw: "lets totally update the body", tags: ["stuff"])
expect(result).to eq(false) expect(result).to eq(false)
expect(post.topic.errors.present?).to eq(true) expect(post.topic.errors.present?).to eq(true)
post.reload post.reload
@ -1281,7 +1324,7 @@ RSpec.describe PostRevisor do
end end
it "can't remove all tags if some are staff-only" do it "can't remove all tags if some are staff-only" do
result = subject.revise!(user, raw: "lets totally update the body", tags: []) result = post_revisor.revise!(user, raw: "lets totally update the body", tags: [])
expect(result).to eq(false) expect(result).to eq(false)
expect(post.topic.errors.present?).to eq(true) expect(post.topic.errors.present?).to eq(true)
post.reload post.reload
@ -1289,14 +1332,15 @@ RSpec.describe PostRevisor do
end end
it "staff-only tags can be removed by staff" do it "staff-only tags can be removed by staff" do
result = subject.revise!(admin, raw: "lets totally update the body", tags: ["stuff"]) result =
post_revisor.revise!(admin, raw: "lets totally update the body", tags: ["stuff"])
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post.topic.tags.map(&:name)).to eq(["stuff"]) expect(post.topic.tags.map(&:name)).to eq(["stuff"])
end end
it "staff can remove all tags" do it "staff can remove all tags" do
result = subject.revise!(admin, raw: "lets totally update the body", tags: []) result = post_revisor.revise!(admin, raw: "lets totally update the body", tags: [])
expect(result).to eq(true) expect(result).to eq(true)
post.reload post.reload
expect(post.topic.tags.size).to eq(0) expect(post.topic.tags.size).to eq(0)
@ -1320,7 +1364,7 @@ RSpec.describe PostRevisor do
it "doesn't bump topic if only staff-only tags are added" do it "doesn't bump topic if only staff-only tags are added" do
expect { expect {
result = result =
subject.revise!( post_revisor.revise!(
Fabricate(:admin), Fabricate(:admin),
raw: post.raw, raw: post.raw,
tags: topic.tags.map(&:name) + ["secret"], tags: topic.tags.map(&:name) + ["secret"],
@ -1332,7 +1376,7 @@ RSpec.describe PostRevisor do
it "doesn't bump topic if only staff-only tags are removed" do it "doesn't bump topic if only staff-only tags are removed" do
expect { expect {
result = result =
subject.revise!( post_revisor.revise!(
Fabricate(:admin), Fabricate(:admin),
raw: post.raw, raw: post.raw,
tags: topic.tags.map(&:name) - %w[important secret], tags: topic.tags.map(&:name) - %w[important secret],
@ -1344,7 +1388,7 @@ RSpec.describe PostRevisor do
it "doesn't bump topic if only staff-only tags are removed and there are no tags left" do it "doesn't bump topic if only staff-only tags are removed and there are no tags left" do
topic.tags = Tag.where(name: %w[important secret]).to_a topic.tags = Tag.where(name: %w[important secret]).to_a
expect { expect {
result = subject.revise!(Fabricate(:admin), raw: post.raw, tags: []) result = post_revisor.revise!(Fabricate(:admin), raw: post.raw, tags: [])
expect(result).to eq(true) expect(result).to eq(true)
}.to_not change { topic.reload.bumped_at } }.to_not change { topic.reload.bumped_at }
end end
@ -1352,7 +1396,7 @@ RSpec.describe PostRevisor do
it "doesn't bump topic if empty string is given" do it "doesn't bump topic if empty string is given" do
topic.tags = Tag.where(name: %w[important secret]).to_a topic.tags = Tag.where(name: %w[important secret]).to_a
expect { expect {
result = subject.revise!(Fabricate(:admin), raw: post.raw, tags: [""]) result = post_revisor.revise!(Fabricate(:admin), raw: post.raw, tags: [""])
expect(result).to eq(true) expect(result).to eq(true)
}.to_not change { topic.reload.bumped_at } }.to_not change { topic.reload.bumped_at }
end end
@ -1360,7 +1404,7 @@ RSpec.describe PostRevisor do
it "should bump topic if non staff-only tags are added" do it "should bump topic if non staff-only tags are added" do
expect { expect {
result = result =
subject.revise!( post_revisor.revise!(
Fabricate(:admin), Fabricate(:admin),
raw: post.raw, raw: post.raw,
tags: topic.tags.map(&:name) + [Fabricate(:tag).name], tags: topic.tags.map(&:name) + [Fabricate(:tag).name],
@ -1370,7 +1414,7 @@ RSpec.describe PostRevisor do
end end
it "creates a hidden revision" do it "creates a hidden revision" do
subject.revise!( post_revisor.revise!(
Fabricate(:admin), Fabricate(:admin),
raw: post.raw, raw: post.raw,
tags: topic.tags.map(&:name) + ["secret"], tags: topic.tags.map(&:name) + ["secret"],
@ -1382,7 +1426,7 @@ RSpec.describe PostRevisor do
PostActionNotifier.enable PostActionNotifier.enable
Jobs.run_immediately! Jobs.run_immediately!
expect { expect {
subject.revise!( post_revisor.revise!(
Fabricate(:admin), Fabricate(:admin),
raw: post.raw, raw: post.raw,
tags: topic.tags.map(&:name) + ["secret"], tags: topic.tags.map(&:name) + ["secret"],
@ -1412,20 +1456,21 @@ RSpec.describe PostRevisor do
it "doesn't allow removing all tags from the group" do it "doesn't allow removing all tags from the group" do
post.topic.tags = [tag1, tag2] post.topic.tags = [tag1, tag2]
result = subject.revise!(user, raw: "lets totally update the body", tags: []) result = post_revisor.revise!(user, raw: "lets totally update the body", tags: [])
expect(result).to eq(false) expect(result).to eq(false)
end end
it "allows removing some tags" do it "allows removing some tags" do
post.topic.tags = [tag1, tag2, tag3] post.topic.tags = [tag1, tag2, tag3]
result = subject.revise!(user, raw: "lets totally update the body", tags: [tag1.name]) result =
post_revisor.revise!(user, raw: "lets totally update the body", tags: [tag1.name])
expect(result).to eq(true) expect(result).to eq(true)
expect(post.reload.topic.tags.map(&:name)).to eq([tag1.name]) expect(post.reload.topic.tags.map(&:name)).to eq([tag1.name])
end end
it "allows admins to remove the tags" do it "allows admins to remove the tags" do
post.topic.tags = [tag1, tag2, tag3] post.topic.tags = [tag1, tag2, tag3]
result = subject.revise!(admin, raw: "lets totally update the body", tags: []) result = post_revisor.revise!(admin, raw: "lets totally update the body", tags: [])
expect(result).to eq(true) expect(result).to eq(true)
expect(post.reload.topic.tags.size).to eq(0) expect(post.reload.topic.tags.size).to eq(0)
end end
@ -1442,7 +1487,11 @@ RSpec.describe PostRevisor do
Fabricate(:tag, name: "totally") Fabricate(:tag, name: "totally")
expect { expect {
@result = @result =
subject.revise!(user, raw: "lets totally update the body", tags: %w[totally update]) post_revisor.revise!(
user,
raw: "lets totally update the body",
tags: %w[totally update],
)
}.to_not change { Tag.count } }.to_not change { Tag.count }
expect(@result).to eq(true) expect(@result).to eq(true)
post.reload post.reload
@ -1467,7 +1516,7 @@ RSpec.describe PostRevisor do
post.link_post_uploads post.link_post_uploads
expect(post.upload_references.pluck(:upload_id)).to contain_exactly(image1.id, image2.id) expect(post.upload_references.pluck(:upload_id)).to contain_exactly(image1.id, image2.id)
subject.revise!(user, raw: <<~RAW) post_revisor.revise!(user, raw: <<~RAW)
This is a post with multiple uploads This is a post with multiple uploads
![image2](#{image2.short_url}) ![image2](#{image2.short_url})
![image3](#{image3.short_url}) ![image3](#{image3.short_url})
@ -1493,7 +1542,7 @@ RSpec.describe PostRevisor do
it "updates the upload secure status, which is secure by default from the composer. set to false for a public topic" do it "updates the upload secure status, which is secure by default from the composer. set to false for a public topic" do
stub_image_size stub_image_size
subject.revise!(user, raw: <<~RAW) post_revisor.revise!(user, raw: <<~RAW)
This is a post with a secure upload This is a post with a secure upload
![image5](#{image5.short_url}) ![image5](#{image5.short_url})
RAW RAW
@ -1507,7 +1556,7 @@ RSpec.describe PostRevisor do
it "does not update the upload secure status, which is secure by default from the composer for a private" do it "does not update the upload secure status, which is secure by default from the composer for a private" do
post.topic.update(category: Fabricate(:private_category, group: Fabricate(:group))) post.topic.update(category: Fabricate(:private_category, group: Fabricate(:group)))
stub_image_size stub_image_size
subject.revise!(user, raw: <<~RAW) post_revisor.revise!(user, raw: <<~RAW)
This is a post with a secure upload This is a post with a secure upload
![image5](#{image5.short_url}) ![image5](#{image5.short_url})
RAW RAW
@ -1554,12 +1603,12 @@ RSpec.describe PostRevisor do
fab!(:post) { Fabricate(:post, raw: "aaa", skip_validation: true) } fab!(:post) { Fabricate(:post, raw: "aaa", skip_validation: true) }
it "can revise multiple times and remove unnecessary revisions" do it "can revise multiple times and remove unnecessary revisions" do
subject.revise!(admin, { raw: "bbb" }, skip_validations: true) post_revisor.revise!(admin, { raw: "bbb" }, skip_validations: true)
expect(post.errors).to be_empty expect(post.errors).to be_empty
# Revert to old version which was invalid to destroy previously created # Revert to old version which was invalid to destroy previously created
# post revision and trigger another post save. # post revision and trigger another post save.
subject.revise!(admin, { raw: "aaa" }, skip_validations: true) post_revisor.revise!(admin, { raw: "aaa" }, skip_validations: true)
expect(post.errors).to be_empty expect(post.errors).to be_empty
end end
end end

View File

@ -203,7 +203,7 @@ RSpec.describe RetrieveTitle do
end end
it "ignores SSRF lookup errors" do it "ignores SSRF lookup errors" do
subject.stubs(:fetch_title).raises(FinalDestination::SSRFDetector::LookupFailedError) described_class.stubs(:fetch_title).raises(FinalDestination::SSRFDetector::LookupFailedError)
expect(RetrieveTitle.crawl("https://example.com")).to eq(nil) expect(RetrieveTitle.crawl("https://example.com")).to eq(nil)
end end

View File

@ -3,10 +3,10 @@
require "seed_data/categories" require "seed_data/categories"
RSpec.describe SeedData::Categories do RSpec.describe SeedData::Categories do
subject { SeedData::Categories.with_default_locale } subject(:seeder) { SeedData::Categories.with_default_locale }
def create_category(name = "staff_category_id") def create_category(name = "staff_category_id")
subject.create(site_setting_names: [name]) seeder.create(site_setting_names: [name])
end end
def description_post(category) def description_post(category)
@ -152,7 +152,7 @@ RSpec.describe SeedData::Categories do
describe "#update" do describe "#update" do
def update_category(name = "staff_category_id", skip_changed: false) def update_category(name = "staff_category_id", skip_changed: false)
subject.update(site_setting_names: [name], skip_changed: skip_changed) seeder.update(site_setting_names: [name], skip_changed: skip_changed)
end end
before do before do
@ -211,7 +211,7 @@ RSpec.describe SeedData::Categories do
{ id: "general_category_id", name: I18n.t("general_category_name"), selected: false }, { id: "general_category_id", name: I18n.t("general_category_name"), selected: false },
] ]
expect(subject.reseed_options).to eq(expected_options) expect(seeder.reseed_options).to eq(expected_options)
end end
end end
end end

View File

@ -3,7 +3,7 @@
require "seed_data/topics" require "seed_data/topics"
RSpec.describe SeedData::Topics do RSpec.describe SeedData::Topics do
subject { SeedData::Topics.with_default_locale } subject(:seeder) { SeedData::Topics.with_default_locale }
before do before do
general_category = Fabricate(:category, name: "General") general_category = Fabricate(:category, name: "General")
@ -11,7 +11,7 @@ RSpec.describe SeedData::Topics do
end end
def create_topic(name = "welcome_topic_id") def create_topic(name = "welcome_topic_id")
subject.create(site_setting_names: [name], include_legal_topics: true) seeder.create(site_setting_names: [name], include_legal_topics: true)
end end
describe "#create" do describe "#create" do
@ -74,7 +74,7 @@ RSpec.describe SeedData::Topics do
end end
it "does not create a legal topic if company_name is not set" do it "does not create a legal topic if company_name is not set" do
subject.create(site_setting_names: ["tos_topic_id"]) seeder.create(site_setting_names: ["tos_topic_id"])
expect(SiteSetting.tos_topic_id).to eq(-1) expect(SiteSetting.tos_topic_id).to eq(-1)
end end
@ -102,7 +102,7 @@ RSpec.describe SeedData::Topics do
it "creates a legal topic if company_name is set" do it "creates a legal topic if company_name is set" do
SiteSetting.company_name = "Company Name" SiteSetting.company_name = "Company Name"
subject.create(site_setting_names: ["tos_topic_id"]) seeder.create(site_setting_names: ["tos_topic_id"])
expect(SiteSetting.tos_topic_id).to_not eq(-1) expect(SiteSetting.tos_topic_id).to_not eq(-1)
end end
@ -110,7 +110,7 @@ RSpec.describe SeedData::Topics do
describe "#update" do describe "#update" do
def update_topic(name = "welcome_topic_id", skip_changed: false) def update_topic(name = "welcome_topic_id", skip_changed: false)
subject.update(site_setting_names: [name], skip_changed: skip_changed) seeder.update(site_setting_names: [name], skip_changed: skip_changed)
end end
it "updates the changed topic" do it "updates the changed topic" do
@ -167,7 +167,7 @@ RSpec.describe SeedData::Topics do
describe "#delete" do describe "#delete" do
def delete_topic(name = "welcome_topic_id", skip_changed: false) def delete_topic(name = "welcome_topic_id", skip_changed: false)
subject.delete(site_setting_names: [name], skip_changed: skip_changed) seeder.delete(site_setting_names: [name], skip_changed: skip_changed)
end end
it "deletes the topic" do it "deletes the topic" do
@ -199,7 +199,7 @@ RSpec.describe SeedData::Topics do
{ id: "welcome_topic_id", name: "Changed Topic Title", selected: false }, { id: "welcome_topic_id", name: "Changed Topic Title", selected: false },
] ]
expect(subject.reseed_options).to eq(expected_options) expect(seeder.reseed_options).to eq(expected_options)
end end
end end
end end

View File

@ -9,8 +9,6 @@ RSpec.describe SiteSettings::TypeSupervisor do
new_settings(provider_local) new_settings(provider_local)
end end
subject { SiteSettings::TypeSupervisor }
describe "constants" do describe "constants" do
it "validator opts are the subset of consumed opts" do it "validator opts are the subset of consumed opts" do
expect( expect(
@ -103,33 +101,33 @@ RSpec.describe SiteSettings::TypeSupervisor do
describe "#parse_value_type" do describe "#parse_value_type" do
it "returns :null type when the value is nil" do it "returns :null type when the value is nil" do
expect(subject.parse_value_type(nil)).to eq(SiteSetting.types[:null]) expect(described_class.parse_value_type(nil)).to eq(SiteSetting.types[:null])
end end
it "returns :integer type when the value is int" do it "returns :integer type when the value is int" do
expect(subject.parse_value_type(2)).to eq(SiteSetting.types[:integer]) expect(described_class.parse_value_type(2)).to eq(SiteSetting.types[:integer])
end end
it "returns :integer type when the value is large int" do it "returns :integer type when the value is large int" do
expect(subject.parse_value_type(99_999_999_999_999_999_999_999_999_999_999_999)).to eq( expect(
SiteSetting.types[:integer], described_class.parse_value_type(99_999_999_999_999_999_999_999_999_999_999_999),
) ).to eq(SiteSetting.types[:integer])
end end
it "returns :float type when the value is float" do it "returns :float type when the value is float" do
expect(subject.parse_value_type(1.23)).to eq(SiteSetting.types[:float]) expect(described_class.parse_value_type(1.23)).to eq(SiteSetting.types[:float])
end end
it "returns :bool type when the value is true" do it "returns :bool type when the value is true" do
expect(subject.parse_value_type(true)).to eq(SiteSetting.types[:bool]) expect(described_class.parse_value_type(true)).to eq(SiteSetting.types[:bool])
end end
it "returns :bool type when the value is false" do it "returns :bool type when the value is false" do
expect(subject.parse_value_type(false)).to eq(SiteSetting.types[:bool]) expect(described_class.parse_value_type(false)).to eq(SiteSetting.types[:bool])
end end
it "raises when the value is not listed" do it "raises when the value is not listed" do
expect { subject.parse_value_type(Object.new) }.to raise_error ArgumentError expect { described_class.parse_value_type(Object.new) }.to raise_error ArgumentError
end end
end end

View File

@ -3,22 +3,24 @@
require "site_settings/validations" require "site_settings/validations"
RSpec.describe SiteSettings::Validations do RSpec.describe SiteSettings::Validations do
subject { Class.new.include(described_class).new } subject(:validations) { Class.new.include(described_class).new }
describe "default_categories" do describe "default_categories" do
fab!(:category) { Fabricate(:category) } fab!(:category) { Fabricate(:category) }
it "supports valid categories" do it "supports valid categories" do
expect { subject.validate_default_categories_watching("#{category.id}") }.not_to raise_error expect {
validations.validate_default_categories_watching("#{category.id}")
}.not_to raise_error
end end
it "won't allow you to input junk categories" do it "won't allow you to input junk categories" do
expect { subject.validate_default_categories_watching("junk") }.to raise_error( expect { validations.validate_default_categories_watching("junk") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
) )
expect { expect {
subject.validate_default_categories_watching("#{category.id}|12312323") validations.validate_default_categories_watching("#{category.id}|12312323")
}.to raise_error(Discourse::InvalidParameters) }.to raise_error(Discourse::InvalidParameters)
end end
@ -85,7 +87,7 @@ RSpec.describe SiteSettings::Validations do
let(:other_setting_name) { "s3_upload_bucket" } let(:other_setting_name) { "s3_upload_bucket" }
def validate(new_value) def validate(new_value)
subject.validate_s3_backup_bucket(new_value) validations.validate_s3_backup_bucket(new_value)
end end
it_behaves_like "s3 bucket validation" it_behaves_like "s3 bucket validation"
@ -103,7 +105,7 @@ RSpec.describe SiteSettings::Validations do
let(:other_setting_name) { "s3_backup_bucket" } let(:other_setting_name) { "s3_backup_bucket" }
def validate(new_value) def validate(new_value)
subject.validate_s3_upload_bucket(new_value) validations.validate_s3_upload_bucket(new_value)
end end
it_behaves_like "s3 bucket validation" it_behaves_like "s3 bucket validation"
@ -142,7 +144,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.enable_local_logins = false } before { SiteSetting.enable_local_logins = false }
it "should raise an error" do it "should raise an error" do
expect { subject.validate_enforce_second_factor("t") }.to raise_error( expect { validations.validate_enforce_second_factor("t") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -153,7 +155,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.enable_local_logins = true } before { SiteSetting.enable_local_logins = true }
it "should be ok" do it "should be ok" do
expect { subject.validate_enforce_second_factor("t") }.not_to raise_error expect { validations.validate_enforce_second_factor("t") }.not_to raise_error
end end
end end
@ -170,7 +172,7 @@ RSpec.describe SiteSettings::Validations do
end end
it "raises and error, and specifies the auth providers" do it "raises and error, and specifies the auth providers" do
expect { subject.validate_enforce_second_factor("all") }.to raise_error( expect { validations.validate_enforce_second_factor("all") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -189,7 +191,7 @@ RSpec.describe SiteSettings::Validations do
end end
it "should raise an error" do it "should raise an error" do
expect { subject.validate_enforce_second_factor("t") }.to raise_error( expect { validations.validate_enforce_second_factor("t") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -207,7 +209,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.enforce_second_factor = "all" } before { SiteSetting.enforce_second_factor = "all" }
it "should raise an error" do it "should raise an error" do
expect { subject.validate_enable_local_logins("f") }.to raise_error( expect { validations.validate_enable_local_logins("f") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -218,14 +220,14 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.enforce_second_factor = "no" } before { SiteSetting.enforce_second_factor = "no" }
it "should be ok" do it "should be ok" do
expect { subject.validate_enable_local_logins("f") }.not_to raise_error expect { validations.validate_enable_local_logins("f") }.not_to raise_error
end end
end end
end end
context "when the new value is true" do context "when the new value is true" do
it "should be ok" do it "should be ok" do
expect { subject.validate_enable_local_logins("t") }.not_to raise_error expect { validations.validate_enable_local_logins("t") }.not_to raise_error
end end
end end
end end
@ -237,7 +239,7 @@ RSpec.describe SiteSettings::Validations do
context "when the new value has trailing slash" do context "when the new value has trailing slash" do
it "should raise an error" do it "should raise an error" do
expect { subject.validate_cors_origins("https://www.rainbows.com/") }.to raise_error( expect { validations.validate_cors_origins("https://www.rainbows.com/") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -248,7 +250,7 @@ RSpec.describe SiteSettings::Validations do
describe "#validate_enable_page_publishing" do describe "#validate_enable_page_publishing" do
context "when the new value is true" do context "when the new value is true" do
it "is ok" do it "is ok" do
expect { subject.validate_enable_page_publishing("t") }.not_to raise_error expect { validations.validate_enable_page_publishing("t") }.not_to raise_error
end end
context "if secure uploads is enabled" do context "if secure uploads is enabled" do
@ -256,7 +258,7 @@ RSpec.describe SiteSettings::Validations do
before { enable_secure_uploads } before { enable_secure_uploads }
it "is not ok" do it "is not ok" do
expect { subject.validate_enable_page_publishing("t") }.to raise_error( expect { validations.validate_enable_page_publishing("t") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -268,13 +270,13 @@ RSpec.describe SiteSettings::Validations do
describe "#validate_s3_use_acls" do describe "#validate_s3_use_acls" do
context "when the new value is true" do context "when the new value is true" do
it "is ok" do it "is ok" do
expect { subject.validate_s3_use_acls("t") }.not_to raise_error expect { validations.validate_s3_use_acls("t") }.not_to raise_error
end end
end end
context "when the new value is false" do context "when the new value is false" do
it "is ok" do it "is ok" do
expect { subject.validate_s3_use_acls("f") }.not_to raise_error expect { validations.validate_s3_use_acls("f") }.not_to raise_error
end end
context "if secure uploads is enabled" do context "if secure uploads is enabled" do
@ -282,7 +284,7 @@ RSpec.describe SiteSettings::Validations do
before { enable_secure_uploads } before { enable_secure_uploads }
it "is not ok" do it "is not ok" do
expect { subject.validate_s3_use_acls("f") }.to raise_error( expect { validations.validate_s3_use_acls("f") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -299,7 +301,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.enable_s3_uploads = true } before { SiteSetting.enable_s3_uploads = true }
it "should be ok" do it "should be ok" do
expect { subject.validate_secure_uploads("t") }.not_to raise_error expect { validations.validate_secure_uploads("t") }.not_to raise_error
end end
end end
@ -307,7 +309,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.enable_s3_uploads = false } before { SiteSetting.enable_s3_uploads = false }
it "is not ok" do it "is not ok" do
expect { subject.validate_secure_uploads("t") }.to raise_error( expect { validations.validate_secure_uploads("t") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -317,7 +319,7 @@ RSpec.describe SiteSettings::Validations do
before { GlobalSetting.stubs(:use_s3?).returns(true) } before { GlobalSetting.stubs(:use_s3?).returns(true) }
it "should be ok" do it "should be ok" do
expect { subject.validate_secure_uploads("t") }.not_to raise_error expect { validations.validate_secure_uploads("t") }.not_to raise_error
end end
end end
end end
@ -326,7 +328,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.s3_use_acls = false } before { SiteSetting.s3_use_acls = false }
it "is not ok" do it "is not ok" do
expect { subject.validate_secure_uploads("t") }.to raise_error( expect { validations.validate_secure_uploads("t") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -345,7 +347,7 @@ RSpec.describe SiteSettings::Validations do
before { GlobalSetting.stubs(:use_s3?).returns(true) } before { GlobalSetting.stubs(:use_s3?).returns(true) }
it "is not ok" do it "is not ok" do
expect { subject.validate_enable_s3_uploads("t") }.to raise_error( expect { validations.validate_enable_s3_uploads("t") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -356,7 +358,7 @@ RSpec.describe SiteSettings::Validations do
before { GlobalSetting.stubs(:use_s3?).returns(false) } before { GlobalSetting.stubs(:use_s3?).returns(false) }
it "should be ok" do it "should be ok" do
expect { subject.validate_enable_s3_uploads("t") }.not_to raise_error expect { validations.validate_enable_s3_uploads("t") }.not_to raise_error
end end
end end
@ -366,7 +368,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.s3_upload_bucket = nil } before { SiteSetting.s3_upload_bucket = nil }
it "is not ok" do it "is not ok" do
expect { subject.validate_enable_s3_uploads("t") }.to raise_error( expect { validations.validate_enable_s3_uploads("t") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -377,7 +379,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.s3_upload_bucket = "some-bucket" } before { SiteSetting.s3_upload_bucket = "some-bucket" }
it "should be ok" do it "should be ok" do
expect { subject.validate_enable_s3_uploads("t") }.not_to raise_error expect { validations.validate_enable_s3_uploads("t") }.not_to raise_error
end end
end end
end end
@ -399,49 +401,47 @@ RSpec.describe SiteSettings::Validations do
end end
it "cannot contain a user agent that's shorter than 3 characters" do it "cannot contain a user agent that's shorter than 3 characters" do
expect { subject.validate_slow_down_crawler_user_agents("ao|acsw") }.to raise_error( expect { validations.validate_slow_down_crawler_user_agents("ao|acsw") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
too_short_message, too_short_message,
) )
expect { subject.validate_slow_down_crawler_user_agents("up") }.to raise_error( expect { validations.validate_slow_down_crawler_user_agents("up") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
too_short_message, too_short_message,
) )
expect { subject.validate_slow_down_crawler_user_agents("a|") }.to raise_error( expect { validations.validate_slow_down_crawler_user_agents("a|") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
too_short_message, too_short_message,
) )
expect { subject.validate_slow_down_crawler_user_agents("|a") }.to raise_error( expect { validations.validate_slow_down_crawler_user_agents("|a") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
too_short_message, too_short_message,
) )
end end
it "allows user agents that are 3 characters or longer" do it "allows user agents that are 3 characters or longer" do
expect { subject.validate_slow_down_crawler_user_agents("aoc") }.not_to raise_error expect { validations.validate_slow_down_crawler_user_agents("aoc") }.not_to raise_error
expect { subject.validate_slow_down_crawler_user_agents("anuq") }.not_to raise_error expect { validations.validate_slow_down_crawler_user_agents("anuq") }.not_to raise_error
expect { subject.validate_slow_down_crawler_user_agents("pupsc|kcx") }.not_to raise_error expect { validations.validate_slow_down_crawler_user_agents("pupsc|kcx") }.not_to raise_error
end end
it "allows the setting to be empty" do it "allows the setting to be empty" do
expect { subject.validate_slow_down_crawler_user_agents("") }.not_to raise_error expect { validations.validate_slow_down_crawler_user_agents("") }.not_to raise_error
end end
it "cannot contain a token of a popular browser user agent" do it "cannot contain a token of a popular browser user agent" do
expect { subject.validate_slow_down_crawler_user_agents("mOzilla") }.to raise_error( expect { validations.validate_slow_down_crawler_user_agents("mOzilla") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
popular_browser_message, popular_browser_message,
) )
expect { subject.validate_slow_down_crawler_user_agents("chRome|badcrawler") }.to raise_error( expect {
Discourse::InvalidParameters, validations.validate_slow_down_crawler_user_agents("chRome|badcrawler")
popular_browser_message, }.to raise_error(Discourse::InvalidParameters, popular_browser_message)
)
expect { subject.validate_slow_down_crawler_user_agents("html|badcrawler") }.to raise_error( expect {
Discourse::InvalidParameters, validations.validate_slow_down_crawler_user_agents("html|badcrawler")
popular_browser_message, }.to raise_error(Discourse::InvalidParameters, popular_browser_message)
)
end end
end end
@ -458,7 +458,7 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.composer_media_optimization_image_enabled = true } before { SiteSetting.composer_media_optimization_image_enabled = true }
it "should raise an error" do it "should raise an error" do
expect { subject.validate_strip_image_metadata("f") }.to raise_error( expect { validations.validate_strip_image_metadata("f") }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
error_message, error_message,
) )
@ -469,14 +469,14 @@ RSpec.describe SiteSettings::Validations do
before { SiteSetting.composer_media_optimization_image_enabled = false } before { SiteSetting.composer_media_optimization_image_enabled = false }
it "should be ok" do it "should be ok" do
expect { subject.validate_strip_image_metadata("f") }.not_to raise_error expect { validations.validate_strip_image_metadata("f") }.not_to raise_error
end end
end end
end end
context "when the new value is true" do context "when the new value is true" do
it "should be ok" do it "should be ok" do
expect { subject.validate_strip_image_metadata("t") }.not_to raise_error expect { validations.validate_strip_image_metadata("t") }.not_to raise_error
end end
end end
end end
@ -485,13 +485,13 @@ RSpec.describe SiteSettings::Validations do
describe "#twitter_summary_large_image" do describe "#twitter_summary_large_image" do
it "does not allow SVG image files" do it "does not allow SVG image files" do
upload = Fabricate(:upload, url: "/images/logo-dark.svg", extension: "svg") upload = Fabricate(:upload, url: "/images/logo-dark.svg", extension: "svg")
expect { subject.validate_twitter_summary_large_image(upload.id) }.to raise_error( expect { validations.validate_twitter_summary_large_image(upload.id) }.to raise_error(
Discourse::InvalidParameters, Discourse::InvalidParameters,
I18n.t("errors.site_settings.twitter_summary_large_image_no_svg"), I18n.t("errors.site_settings.twitter_summary_large_image_no_svg"),
) )
upload.update!(url: "/images/logo-dark.png", extension: "png") upload.update!(url: "/images/logo-dark.png", extension: "png")
expect { subject.validate_twitter_summary_large_image(upload.id) }.not_to raise_error expect { validations.validate_twitter_summary_large_image(upload.id) }.not_to raise_error
expect { subject.validate_twitter_summary_large_image(nil) }.not_to raise_error expect { validations.validate_twitter_summary_large_image(nil) }.not_to raise_error
end end
end end
end end

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe TopicUploadSecurityManager do RSpec.describe TopicUploadSecurityManager do
subject(:manager) { described_class.new(topic) }
let(:group) { Fabricate(:group) } let(:group) { Fabricate(:group) }
let(:category) { Fabricate(:category) } let(:category) { Fabricate(:category) }
let!(:topic) { Fabricate(:topic, user: user, category: category) } let!(:topic) { Fabricate(:topic, user: user, category: category) }
@ -10,8 +12,6 @@ RSpec.describe TopicUploadSecurityManager do
let!(:post3) { Fabricate(:post, topic: topic) } let!(:post3) { Fabricate(:post, topic: topic) }
let!(:post4) { Fabricate(:post, topic: topic) } let!(:post4) { Fabricate(:post, topic: topic) }
subject { described_class.new(topic) }
context "when a topic has posts linked to secure uploads" do context "when a topic has posts linked to secure uploads" do
let!(:upload) { Fabricate(:secure_upload) } let!(:upload) { Fabricate(:secure_upload) }
let!(:upload2) { Fabricate(:secure_upload) } let!(:upload2) { Fabricate(:secure_upload) }
@ -127,7 +127,7 @@ RSpec.describe TopicUploadSecurityManager do
it "changes the upload secure status to true and changes the ACL and rebakes the post and sets the access control post" do it "changes the upload secure status to true and changes the ACL and rebakes the post and sets the access control post" do
Post.any_instance.expects(:rebake!).once Post.any_instance.expects(:rebake!).once
subject.run manager.run
expect(upload3.reload.secure?).to eq(true) expect(upload3.reload.secure?).to eq(true)
expect(upload3.reload.access_control_post).to eq(post4) expect(upload3.reload.access_control_post).to eq(post4)
end end
@ -136,7 +136,7 @@ RSpec.describe TopicUploadSecurityManager do
before { SiteSetting.secure_uploads = false } before { SiteSetting.secure_uploads = false }
it "does not change the upload secure status and does not set the access control post" do it "does not change the upload secure status and does not set the access control post" do
subject.run manager.run
expect(upload3.reload.secure?).to eq(false) expect(upload3.reload.secure?).to eq(false)
expect(upload3.reload.access_control_post).to eq(nil) expect(upload3.reload.access_control_post).to eq(nil)
end end
@ -151,7 +151,7 @@ RSpec.describe TopicUploadSecurityManager do
it "does not change the upload secure status and does not set the access control post" do it "does not change the upload secure status and does not set the access control post" do
Post.any_instance.expects(:rebake!).never Post.any_instance.expects(:rebake!).never
subject.run manager.run
expect(upload3.reload.secure?).to eq(false) expect(upload3.reload.secure?).to eq(false)
expect(upload3.reload.access_control_post).to eq(nil) expect(upload3.reload.access_control_post).to eq(nil)
end end
@ -161,14 +161,14 @@ RSpec.describe TopicUploadSecurityManager do
def expect_upload_status_not_to_change def expect_upload_status_not_to_change
Post.any_instance.expects(:rebake!).never Post.any_instance.expects(:rebake!).never
subject.run manager.run
expect(upload.reload.secure?).to eq(true) expect(upload.reload.secure?).to eq(true)
expect(upload2.reload.secure?).to eq(true) expect(upload2.reload.secure?).to eq(true)
end end
def expect_upload_status_to_change_and_rebake def expect_upload_status_to_change_and_rebake
Post.any_instance.expects(:rebake!).twice Post.any_instance.expects(:rebake!).twice
subject.run manager.run
expect(upload.reload.secure?).to eq(false) expect(upload.reload.secure?).to eq(false)
expect(upload2.reload.secure?).to eq(false) expect(upload2.reload.secure?).to eq(false)
end end

View File

@ -1,16 +1,17 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe UploadSecurity do RSpec.describe UploadSecurity do
subject(:security) { described_class.new(upload, opts) }
fab!(:private_category) { Fabricate(:private_category, group: Fabricate(:group)) } fab!(:private_category) { Fabricate(:private_category, group: Fabricate(:group)) }
fab!(:post_in_secure_context) do fab!(:post_in_secure_context) do
Fabricate(:post, topic: Fabricate(:topic, category: private_category)) Fabricate(:post, topic: Fabricate(:topic, category: private_category))
end end
fab!(:upload) { Fabricate(:upload) } fab!(:upload) { Fabricate(:upload) }
let(:type) { nil } let(:type) { nil }
let(:opts) { { type: type, creating: creating } } let(:opts) { { type: type, creating: creating } }
subject { described_class.new(upload, opts) }
context "when secure uploads is enabled" do context "when secure uploads is enabled" do
before do before do
setup_s3 setup_s3
@ -24,63 +25,63 @@ RSpec.describe UploadSecurity do
before { SiteSetting.login_required = true } before { SiteSetting.login_required = true }
it "returns true" do it "returns true" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
context "when uploading in public context" do context "when uploading in public context" do
describe "for a public type badge_image" do describe "for a public type badge_image" do
let(:type) { "badge_image" } let(:type) { "badge_image" }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
describe "for a public type group_flair" do describe "for a public type group_flair" do
let(:type) { "group_flair" } let(:type) { "group_flair" }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
describe "for a public type avatar" do describe "for a public type avatar" do
let(:type) { "avatar" } let(:type) { "avatar" }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
describe "for a public type custom_emoji" do describe "for a public type custom_emoji" do
let(:type) { "custom_emoji" } let(:type) { "custom_emoji" }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
describe "for a public type profile_background" do describe "for a public type profile_background" do
let(:type) { "profile_background" } let(:type) { "profile_background" }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
describe "for a public type avatar" do describe "for a public type avatar" do
let(:type) { "avatar" } let(:type) { "avatar" }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
describe "for a public type category_logo" do describe "for a public type category_logo" do
let(:type) { "category_logo" } let(:type) { "category_logo" }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
describe "for a public type category_background" do describe "for a public type category_background" do
let(:type) { "category_background" } let(:type) { "category_background" }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -88,12 +89,12 @@ RSpec.describe UploadSecurity do
let(:type) { "my_custom_type" } let(:type) { "my_custom_type" }
it "returns true if the custom type has not been added" do it "returns true if the custom type has not been added" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
it "returns false if the custom type has been added" do it "returns false if the custom type has been added" do
UploadSecurity.register_custom_public_type(type) UploadSecurity.register_custom_public_type(type)
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
UploadSecurity.reset_custom_public_types UploadSecurity.reset_custom_public_types
end end
end end
@ -102,7 +103,7 @@ RSpec.describe UploadSecurity do
before { upload.stubs(:for_theme).returns(true) } before { upload.stubs(:for_theme).returns(true) }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -110,7 +111,7 @@ RSpec.describe UploadSecurity do
before { upload.stubs(:for_site_setting).returns(true) } before { upload.stubs(:for_site_setting).returns(true) }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -118,7 +119,7 @@ RSpec.describe UploadSecurity do
before { upload.stubs(:for_gravatar).returns(true) } before { upload.stubs(:for_gravatar).returns(true) }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -129,7 +130,7 @@ RSpec.describe UploadSecurity do
e.url == "/images/emoji/twitter/falafel.png?v=#{Emoji::EMOJI_VERSION}" e.url == "/images/emoji/twitter/falafel.png?v=#{Emoji::EMOJI_VERSION}"
end end
upload.update!(origin: "http://localhost:3000#{falafel.url}") upload.update!(origin: "http://localhost:3000#{falafel.url}")
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
end end
@ -139,14 +140,14 @@ RSpec.describe UploadSecurity do
before { upload.update(access_control_post_id: post_in_secure_context.id) } before { upload.update(access_control_post_id: post_in_secure_context.id) }
it "returns true" do it "returns true" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
context "when the post is deleted" do context "when the post is deleted" do
before { post_in_secure_context.trash! } before { post_in_secure_context.trash! }
it "still determines whether the post has secure uploads; returns true" do it "still determines whether the post has secure uploads; returns true" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
end end
end end
@ -154,28 +155,28 @@ RSpec.describe UploadSecurity do
context "when uploading in the composer" do context "when uploading in the composer" do
let(:type) { "composer" } let(:type) { "composer" }
it "returns true" do it "returns true" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
end end
context "when uploading for a group message" do context "when uploading for a group message" do
before { upload.stubs(:for_group_message).returns(true) } before { upload.stubs(:for_group_message).returns(true) }
it "returns true" do it "returns true" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
end end
context "when uploading for a PM" do context "when uploading for a PM" do
before { upload.stubs(:for_private_message).returns(true) } before { upload.stubs(:for_private_message).returns(true) }
it "returns true" do it "returns true" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
end end
context "when upload is already secure" do context "when upload is already secure" do
before { upload.update(secure: true) } before { upload.update(secure: true) }
it "returns true" do it "returns true" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
end end
@ -185,7 +186,7 @@ RSpec.describe UploadSecurity do
context "when the access control post has_secure_uploads?" do context "when the access control post has_secure_uploads?" do
before { upload.update(access_control_post: post_in_secure_context) } before { upload.update(access_control_post: post_in_secure_context) }
it "returns true" do it "returns true" do
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
end end
end end
@ -213,7 +214,7 @@ RSpec.describe UploadSecurity do
describe "when the upload is first used for a post in a secure context" do describe "when the upload is first used for a post in a secure context" do
it "returns true" do it "returns true" do
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(true) expect(security.should_be_secure?).to eq(true)
end end
end end
@ -223,7 +224,7 @@ RSpec.describe UploadSecurity do
post_in_secure_context.trash! post_in_secure_context.trash!
CustomEmoji.create(name: "meme", upload: upload) CustomEmoji.create(name: "meme", upload: upload)
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -231,7 +232,7 @@ RSpec.describe UploadSecurity do
it "returns false" do it "returns false" do
SiteSetting.favicon = upload SiteSetting.favicon = upload
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -239,7 +240,7 @@ RSpec.describe UploadSecurity do
it "returns false" do it "returns false" do
Fabricate(:theme_field, type_id: ThemeField.types[:theme_upload_var], upload: upload) Fabricate(:theme_field, type_id: ThemeField.types[:theme_upload_var], upload: upload)
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -247,7 +248,7 @@ RSpec.describe UploadSecurity do
it "returns false" do it "returns false" do
Fabricate(:group, flair_upload: upload) Fabricate(:group, flair_upload: upload)
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -255,7 +256,7 @@ RSpec.describe UploadSecurity do
it "returns false" do it "returns false" do
CustomEmoji.create(name: "meme", upload: upload) CustomEmoji.create(name: "meme", upload: upload)
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
context "when the created_at dates for upload references are identical" do context "when the created_at dates for upload references are identical" do
@ -266,7 +267,7 @@ RSpec.describe UploadSecurity do
UploadReference.find_by(target: custom_emoji).update!(created_at: now) UploadReference.find_by(target: custom_emoji).update!(created_at: now)
UploadReference.find_by(target: post_in_secure_context).update!(created_at: now) UploadReference.find_by(target: post_in_secure_context).update!(created_at: now)
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
end end
@ -275,7 +276,7 @@ RSpec.describe UploadSecurity do
it "returns false" do it "returns false" do
Fabricate(:badge, image_upload: upload) Fabricate(:badge, image_upload: upload)
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -283,7 +284,7 @@ RSpec.describe UploadSecurity do
it "returns false" do it "returns false" do
Fabricate(:category, uploaded_logo: upload) Fabricate(:category, uploaded_logo: upload)
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -292,7 +293,7 @@ RSpec.describe UploadSecurity do
user = Fabricate(:user) user = Fabricate(:user)
user.user_profile.update!(card_background_upload: upload) user.user_profile.update!(card_background_upload: upload)
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -300,7 +301,7 @@ RSpec.describe UploadSecurity do
it "returns false" do it "returns false" do
Fabricate(:user, uploaded_avatar: upload) Fabricate(:user, uploaded_avatar: upload)
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
@ -308,7 +309,7 @@ RSpec.describe UploadSecurity do
it "returns false" do it "returns false" do
Fabricate(:user_avatar, custom_upload: upload) Fabricate(:user_avatar, custom_upload: upload)
create_secure_post_reference create_secure_post_reference
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
end end
@ -320,14 +321,14 @@ RSpec.describe UploadSecurity do
before { SiteSetting.secure_uploads = false } before { SiteSetting.secure_uploads = false }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
context "for attachments" do context "for attachments" do
before { upload.update(original_filename: "test.pdf") } before { upload.update(original_filename: "test.pdf") }
it "returns false" do it "returns false" do
expect(subject.should_be_secure?).to eq(false) expect(security.should_be_secure?).to eq(false)
end end
end end
end end

View File

@ -1,18 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe UserCommScreener do RSpec.describe UserCommScreener do
fab!(:target_user1) { Fabricate(:user, username: "bobscreen") } subject(:screener) do
fab!(:target_user2) { Fabricate(:user, username: "hughscreen") }
fab!(:target_user3) do
user = Fabricate(:user, username: "alicescreen")
user.user_option.update(allow_private_messages: false)
user
end
fab!(:target_user4) { Fabricate(:user, username: "janescreen") }
fab!(:target_user5) { Fabricate(:user, username: "maryscreen") }
fab!(:other_user) { Fabricate(:user) }
subject do
described_class.new( described_class.new(
acting_user: acting_user, acting_user: acting_user,
target_user_ids: [ target_user_ids: [
@ -25,6 +14,17 @@ RSpec.describe UserCommScreener do
) )
end end
fab!(:target_user1) { Fabricate(:user, username: "bobscreen") }
fab!(:target_user2) { Fabricate(:user, username: "hughscreen") }
fab!(:target_user3) do
user = Fabricate(:user, username: "alicescreen")
user.user_option.update(allow_private_messages: false)
user
end
fab!(:target_user4) { Fabricate(:user, username: "janescreen") }
fab!(:target_user5) { Fabricate(:user, username: "maryscreen") }
fab!(:other_user) { Fabricate(:user) }
it "allows initializing the class with both an acting_user_id and an acting_user" do it "allows initializing the class with both an acting_user_id and an acting_user" do
acting_user = Fabricate(:user) acting_user = Fabricate(:user)
screener = described_class.new(acting_user: acting_user, target_user_ids: [target_user1.id]) screener = described_class.new(acting_user: acting_user, target_user_ids: [target_user1.id])
@ -58,7 +58,7 @@ RSpec.describe UserCommScreener do
describe "#allowing_actor_communication" do describe "#allowing_actor_communication" do
it "returns the usernames of people not ignoring, muting, or disallowing PMs from the actor" do it "returns the usernames of people not ignoring, muting, or disallowing PMs from the actor" do
expect(subject.allowing_actor_communication).to match_array( expect(screener.allowing_actor_communication).to match_array(
[target_user4.id, target_user5.id], [target_user4.id, target_user5.id],
) )
end end
@ -66,7 +66,7 @@ RSpec.describe UserCommScreener do
describe "#preventing_actor_communication" do describe "#preventing_actor_communication" do
it "returns the usernames of people ignoring, muting, or disallowing PMs from the actor" do it "returns the usernames of people ignoring, muting, or disallowing PMs from the actor" do
expect(subject.preventing_actor_communication).to match_array( expect(screener.preventing_actor_communication).to match_array(
[target_user1.id, target_user2.id, target_user3.id], [target_user1.id, target_user2.id, target_user3.id],
) )
end end
@ -74,23 +74,23 @@ RSpec.describe UserCommScreener do
describe "#ignoring_or_muting_actor?" do describe "#ignoring_or_muting_actor?" do
it "does not raise an error when looking for a user who has no communication preferences" do it "does not raise an error when looking for a user who has no communication preferences" do
expect { subject.ignoring_or_muting_actor?(target_user5.id) }.not_to raise_error expect { screener.ignoring_or_muting_actor?(target_user5.id) }.not_to raise_error
end end
it "returns true for a user muting the actor" do it "returns true for a user muting the actor" do
expect(subject.ignoring_or_muting_actor?(target_user1.id)).to eq(true) expect(screener.ignoring_or_muting_actor?(target_user1.id)).to eq(true)
end end
it "returns true for a user ignoring the actor" do it "returns true for a user ignoring the actor" do
expect(subject.ignoring_or_muting_actor?(target_user2.id)).to eq(true) expect(screener.ignoring_or_muting_actor?(target_user2.id)).to eq(true)
end end
it "returns false for a user neither ignoring or muting the actor" do it "returns false for a user neither ignoring or muting the actor" do
expect(subject.ignoring_or_muting_actor?(target_user3.id)).to eq(false) expect(screener.ignoring_or_muting_actor?(target_user3.id)).to eq(false)
end end
it "raises a NotFound error if the user_id passed in is not part of the target users" do it "raises a NotFound error if the user_id passed in is not part of the target users" do
expect { subject.ignoring_or_muting_actor?(other_user.id) }.to raise_error( expect { screener.ignoring_or_muting_actor?(other_user.id) }.to raise_error(
Discourse::NotFound, Discourse::NotFound,
) )
end end
@ -98,34 +98,34 @@ RSpec.describe UserCommScreener do
describe "#disallowing_pms_from_actor?" do describe "#disallowing_pms_from_actor?" do
it "returns true for a user disallowing all PMs" do it "returns true for a user disallowing all PMs" do
expect(subject.disallowing_pms_from_actor?(target_user3.id)).to eq(true) expect(screener.disallowing_pms_from_actor?(target_user3.id)).to eq(true)
end end
it "returns true for a user allowing only PMs for certain users but not the actor" do it "returns true for a user allowing only PMs for certain users but not the actor" do
target_user4.user_option.update!(enable_allowed_pm_users: true) target_user4.user_option.update!(enable_allowed_pm_users: true)
expect(subject.disallowing_pms_from_actor?(target_user4.id)).to eq(true) expect(screener.disallowing_pms_from_actor?(target_user4.id)).to eq(true)
end end
it "returns false for a user allowing only PMs for certain users which the actor allowed" do it "returns false for a user allowing only PMs for certain users which the actor allowed" do
target_user4.user_option.update!(enable_allowed_pm_users: true) target_user4.user_option.update!(enable_allowed_pm_users: true)
AllowedPmUser.create!(user: target_user4, allowed_pm_user: acting_user) AllowedPmUser.create!(user: target_user4, allowed_pm_user: acting_user)
expect(subject.disallowing_pms_from_actor?(target_user4.id)).to eq(false) expect(screener.disallowing_pms_from_actor?(target_user4.id)).to eq(false)
end end
it "returns false for a user not disallowing PMs or muting or ignoring" do it "returns false for a user not disallowing PMs or muting or ignoring" do
expect(subject.disallowing_pms_from_actor?(target_user5.id)).to eq(false) expect(screener.disallowing_pms_from_actor?(target_user5.id)).to eq(false)
end end
it "returns true for a user not disallowing PMs but still ignoring" do it "returns true for a user not disallowing PMs but still ignoring" do
expect(subject.disallowing_pms_from_actor?(target_user1.id)).to eq(true) expect(screener.disallowing_pms_from_actor?(target_user1.id)).to eq(true)
end end
it "returns true for a user not disallowing PMs but still muting" do it "returns true for a user not disallowing PMs but still muting" do
expect(subject.disallowing_pms_from_actor?(target_user2.id)).to eq(true) expect(screener.disallowing_pms_from_actor?(target_user2.id)).to eq(true)
end end
it "raises a NotFound error if the user_id passed in is not part of the target users" do it "raises a NotFound error if the user_id passed in is not part of the target users" do
expect { subject.disallowing_pms_from_actor?(other_user.id) }.to raise_error( expect { screener.disallowing_pms_from_actor?(other_user.id) }.to raise_error(
Discourse::NotFound, Discourse::NotFound,
) )
end end
@ -146,7 +146,7 @@ RSpec.describe UserCommScreener do
describe "#allowing_actor_communication" do describe "#allowing_actor_communication" do
it "returns all usernames since staff can communicate with anyone" do it "returns all usernames since staff can communicate with anyone" do
expect(subject.allowing_actor_communication).to match_array( expect(screener.allowing_actor_communication).to match_array(
[target_user1.id, target_user2.id, target_user3.id, target_user4.id, target_user5.id], [target_user1.id, target_user2.id, target_user3.id, target_user4.id, target_user5.id],
) )
end end
@ -154,25 +154,25 @@ RSpec.describe UserCommScreener do
describe "#preventing_actor_communication" do describe "#preventing_actor_communication" do
it "does not return any usernames since no users can prevent staff communicating with them" do it "does not return any usernames since no users can prevent staff communicating with them" do
expect(subject.preventing_actor_communication).to eq([]) expect(screener.preventing_actor_communication).to eq([])
end end
end end
describe "#ignoring_or_muting_actor?" do describe "#ignoring_or_muting_actor?" do
it "returns false for a user muting the staff" do it "returns false for a user muting the staff" do
expect(subject.ignoring_or_muting_actor?(target_user1.id)).to eq(false) expect(screener.ignoring_or_muting_actor?(target_user1.id)).to eq(false)
end end
it "returns false for a user ignoring the staff actor" do it "returns false for a user ignoring the staff actor" do
expect(subject.ignoring_or_muting_actor?(target_user2.id)).to eq(false) expect(screener.ignoring_or_muting_actor?(target_user2.id)).to eq(false)
end end
it "returns false for a user neither ignoring or muting the actor" do it "returns false for a user neither ignoring or muting the actor" do
expect(subject.ignoring_or_muting_actor?(target_user3.id)).to eq(false) expect(screener.ignoring_or_muting_actor?(target_user3.id)).to eq(false)
end end
it "raises a NotFound error if the user_id passed in is not part of the target users" do it "raises a NotFound error if the user_id passed in is not part of the target users" do
expect { subject.ignoring_or_muting_actor?(other_user.id) }.to raise_error( expect { screener.ignoring_or_muting_actor?(other_user.id) }.to raise_error(
Discourse::NotFound, Discourse::NotFound,
) )
end end
@ -180,28 +180,28 @@ RSpec.describe UserCommScreener do
describe "#disallowing_pms_from_actor?" do describe "#disallowing_pms_from_actor?" do
it "returns false for a user disallowing all PMs" do it "returns false for a user disallowing all PMs" do
expect(subject.disallowing_pms_from_actor?(target_user3.id)).to eq(false) expect(screener.disallowing_pms_from_actor?(target_user3.id)).to eq(false)
end end
it "returns false for a user allowing only PMs for certain users but not the actor" do it "returns false for a user allowing only PMs for certain users but not the actor" do
target_user4.user_option.update!(enable_allowed_pm_users: true) target_user4.user_option.update!(enable_allowed_pm_users: true)
expect(subject.disallowing_pms_from_actor?(target_user4.id)).to eq(false) expect(screener.disallowing_pms_from_actor?(target_user4.id)).to eq(false)
end end
it "returns false for a user not disallowing PMs or muting or ignoring" do it "returns false for a user not disallowing PMs or muting or ignoring" do
expect(subject.disallowing_pms_from_actor?(target_user5.id)).to eq(false) expect(screener.disallowing_pms_from_actor?(target_user5.id)).to eq(false)
end end
it "returns false for a user not disallowing PMs but still ignoring" do it "returns false for a user not disallowing PMs but still ignoring" do
expect(subject.disallowing_pms_from_actor?(target_user1.id)).to eq(false) expect(screener.disallowing_pms_from_actor?(target_user1.id)).to eq(false)
end end
it "returns false for a user not disallowing PMs but still muting" do it "returns false for a user not disallowing PMs but still muting" do
expect(subject.disallowing_pms_from_actor?(target_user2.id)).to eq(false) expect(screener.disallowing_pms_from_actor?(target_user2.id)).to eq(false)
end end
it "raises a NotFound error if the user_id passed in is not part of the target users" do it "raises a NotFound error if the user_id passed in is not part of the target users" do
expect { subject.disallowing_pms_from_actor?(other_user.id) }.to raise_error( expect { screener.disallowing_pms_from_actor?(other_user.id) }.to raise_error(
Discourse::NotFound, Discourse::NotFound,
) )
end end
@ -232,13 +232,13 @@ RSpec.describe UserCommScreener do
describe "#actor_preventing_communication" do describe "#actor_preventing_communication" do
it "returns the user_ids of the users the actor is ignoring, muting, or disallowing PMs from" do it "returns the user_ids of the users the actor is ignoring, muting, or disallowing PMs from" do
acting_user.user_option.update!(enable_allowed_pm_users: true) acting_user.user_option.update!(enable_allowed_pm_users: true)
expect(subject.actor_preventing_communication).to match_array( expect(screener.actor_preventing_communication).to match_array(
[target_user1.id, target_user2.id, target_user3.id, target_user5.id], [target_user1.id, target_user2.id, target_user3.id, target_user5.id],
) )
end end
it "does not include users the actor is disallowing PMs from if they have not set enable_allowed_pm_users" do it "does not include users the actor is disallowing PMs from if they have not set enable_allowed_pm_users" do
expect(subject.actor_preventing_communication).to match_array( expect(screener.actor_preventing_communication).to match_array(
[target_user1.id, target_user2.id], [target_user1.id, target_user2.id],
) )
end end
@ -250,7 +250,7 @@ RSpec.describe UserCommScreener do
end end
it "returns an empty array and does not error" do it "returns an empty array and does not error" do
expect(subject.actor_preventing_communication).to match_array([]) expect(screener.actor_preventing_communication).to match_array([])
end end
end end
end end
@ -258,7 +258,7 @@ RSpec.describe UserCommScreener do
describe "#actor_allowing_communication" do describe "#actor_allowing_communication" do
it "returns the user_ids of the users who the actor is not ignoring, muting, or disallowing PMs from" do it "returns the user_ids of the users who the actor is not ignoring, muting, or disallowing PMs from" do
acting_user.user_option.update!(enable_allowed_pm_users: true) acting_user.user_option.update!(enable_allowed_pm_users: true)
expect(subject.actor_allowing_communication).to match_array([target_user4.id]) expect(screener.actor_allowing_communication).to match_array([target_user4.id])
end end
describe "when the actor has no preferences" do describe "when the actor has no preferences" do
@ -268,7 +268,7 @@ RSpec.describe UserCommScreener do
end end
it "returns an array of the target users and does not error" do it "returns an array of the target users and does not error" do
expect(subject.actor_allowing_communication).to match_array( expect(screener.actor_allowing_communication).to match_array(
[target_user1.id, target_user2.id, target_user3.id, target_user4.id, target_user5.id], [target_user1.id, target_user2.id, target_user3.id, target_user4.id, target_user5.id],
) )
end end
@ -277,49 +277,51 @@ RSpec.describe UserCommScreener do
describe "#actor_ignoring?" do describe "#actor_ignoring?" do
it "returns true for user ids that the actor is ignoring" do it "returns true for user ids that the actor is ignoring" do
expect(subject.actor_ignoring?(target_user2.id)).to eq(true) expect(screener.actor_ignoring?(target_user2.id)).to eq(true)
expect(subject.actor_ignoring?(target_user4.id)).to eq(false) expect(screener.actor_ignoring?(target_user4.id)).to eq(false)
end end
it "raises a NotFound error if the user_id passed in is not part of the target users" do it "raises a NotFound error if the user_id passed in is not part of the target users" do
expect { subject.actor_ignoring?(other_user.id) }.to raise_error(Discourse::NotFound) expect { screener.actor_ignoring?(other_user.id) }.to raise_error(Discourse::NotFound)
end end
end end
describe "#actor_muting?" do describe "#actor_muting?" do
it "returns true for user ids that the actor is muting" do it "returns true for user ids that the actor is muting" do
expect(subject.actor_muting?(target_user1.id)).to eq(true) expect(screener.actor_muting?(target_user1.id)).to eq(true)
expect(subject.actor_muting?(target_user2.id)).to eq(false) expect(screener.actor_muting?(target_user2.id)).to eq(false)
end end
it "raises a NotFound error if the user_id passed in is not part of the target users" do it "raises a NotFound error if the user_id passed in is not part of the target users" do
expect { subject.actor_muting?(other_user.id) }.to raise_error(Discourse::NotFound) expect { screener.actor_muting?(other_user.id) }.to raise_error(Discourse::NotFound)
end end
end end
describe "#actor_disallowing_pms?" do describe "#actor_disallowing_pms?" do
it "returns true for user ids that the actor is not explicitly allowing PMs from" do it "returns true for user ids that the actor is not explicitly allowing PMs from" do
acting_user.user_option.update!(enable_allowed_pm_users: true) acting_user.user_option.update!(enable_allowed_pm_users: true)
expect(subject.actor_disallowing_pms?(target_user3.id)).to eq(true) expect(screener.actor_disallowing_pms?(target_user3.id)).to eq(true)
expect(subject.actor_disallowing_pms?(target_user1.id)).to eq(false) expect(screener.actor_disallowing_pms?(target_user1.id)).to eq(false)
end end
it "returns true if the actor has disallowed all PMs" do it "returns true if the actor has disallowed all PMs" do
acting_user.user_option.update!(allow_private_messages: false) acting_user.user_option.update!(allow_private_messages: false)
expect(subject.actor_disallowing_pms?(target_user3.id)).to eq(true) expect(screener.actor_disallowing_pms?(target_user3.id)).to eq(true)
expect(subject.actor_disallowing_pms?(target_user1.id)).to eq(true) expect(screener.actor_disallowing_pms?(target_user1.id)).to eq(true)
end end
it "raises a NotFound error if the user_id passed in is not part of the target users" do it "raises a NotFound error if the user_id passed in is not part of the target users" do
expect { subject.actor_disallowing_pms?(other_user.id) }.to raise_error(Discourse::NotFound) expect { screener.actor_disallowing_pms?(other_user.id) }.to raise_error(
Discourse::NotFound,
)
end end
end end
describe "#actor_disallowing_all_pms?" do describe "#actor_disallowing_all_pms?" do
it "returns true if the acting user has disabled private messages altogether" do it "returns true if the acting user has disabled private messages altogether" do
expect(subject.actor_disallowing_all_pms?).to eq(false) expect(screener.actor_disallowing_all_pms?).to eq(false)
acting_user.user_option.update!(allow_private_messages: false) acting_user.user_option.update!(allow_private_messages: false)
expect(subject.actor_disallowing_all_pms?).to eq(true) expect(screener.actor_disallowing_all_pms?).to eq(true)
end end
end end
end end

View File

@ -1,9 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe AllowedIpAddressValidator do RSpec.describe AllowedIpAddressValidator do
subject(:validate) { validator.validate_each(record, :ip_address, record.ip_address) }
let(:record) { Fabricate.build(:user, trust_level: TrustLevel[0], ip_address: "99.232.23.123") } let(:record) { Fabricate.build(:user, trust_level: TrustLevel[0], ip_address: "99.232.23.123") }
let(:validator) { described_class.new(attributes: :ip_address) } let(:validator) { described_class.new(attributes: :ip_address) }
subject(:validate) { validator.validate_each(record, :ip_address, record.ip_address) }
context "when ip address should be blocked" do context "when ip address should be blocked" do
it "should add an error" do it "should add an error" do

View File

@ -1,21 +1,21 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe CssColorValidator do RSpec.describe CssColorValidator do
subject { described_class.new } subject(:validator) { described_class.new }
it "validates hex colors" do it "validates hex colors" do
expect(subject.valid_value?("#0")).to eq(false) expect(validator.valid_value?("#0")).to eq(false)
expect(subject.valid_value?("#00")).to eq(false) expect(validator.valid_value?("#00")).to eq(false)
expect(subject.valid_value?("#000")).to eq(true) expect(validator.valid_value?("#000")).to eq(true)
expect(subject.valid_value?("#0000")).to eq(false) expect(validator.valid_value?("#0000")).to eq(false)
expect(subject.valid_value?("#00000")).to eq(false) expect(validator.valid_value?("#00000")).to eq(false)
expect(subject.valid_value?("#000000")).to eq(true) expect(validator.valid_value?("#000000")).to eq(true)
end end
it "validates css colors" do it "validates css colors" do
expect(subject.valid_value?("red")).to eq(true) expect(validator.valid_value?("red")).to eq(true)
expect(subject.valid_value?("green")).to eq(true) expect(validator.valid_value?("green")).to eq(true)
expect(subject.valid_value?("blue")).to eq(true) expect(validator.valid_value?("blue")).to eq(true)
expect(subject.valid_value?("hello")).to eq(false) expect(validator.valid_value?("hello")).to eq(false)
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe EnableLocalLoginsViaEmailValidator do RSpec.describe EnableLocalLoginsViaEmailValidator do
subject { described_class.new } subject(:validator) { described_class.new }
describe "#valid_value?" do describe "#valid_value?" do
describe "when 'enable_local_logins' is false" do describe "when 'enable_local_logins' is false" do
@ -9,15 +9,15 @@ RSpec.describe EnableLocalLoginsViaEmailValidator do
describe "when val is false" do describe "when val is false" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
end end
end end
describe "when value is true" do describe "when value is true" do
it "should not be valid" do it "should not be valid" do
expect(subject.valid_value?("t")).to eq(false) expect(validator.valid_value?("t")).to eq(false)
expect(subject.error_message).to eq( expect(validator.error_message).to eq(
I18n.t("site_settings.errors.enable_local_logins_disabled"), I18n.t("site_settings.errors.enable_local_logins_disabled"),
) )
end end
@ -29,13 +29,13 @@ RSpec.describe EnableLocalLoginsViaEmailValidator do
describe "when val is false" do describe "when val is false" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
end end
end end
describe "when value is true" do describe "when value is true" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("t")).to eq(true) expect(validator.valid_value?("t")).to eq(true)
end end
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe EnableSsoValidator do RSpec.describe EnableSsoValidator do
subject { described_class.new } subject(:validator) { described_class.new }
describe "#valid_value?" do describe "#valid_value?" do
describe "when 'sso url' is empty" do describe "when 'sso url' is empty" do
@ -9,15 +9,15 @@ RSpec.describe EnableSsoValidator do
describe "when val is false" do describe "when val is false" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
end end
end end
describe "when value is true" do describe "when value is true" do
it "should not be valid" do it "should not be valid" do
expect(subject.valid_value?("t")).to eq(false) expect(validator.valid_value?("t")).to eq(false)
expect(subject.error_message).to eq( expect(validator.error_message).to eq(
I18n.t("site_settings.errors.discourse_connect_url_is_empty"), I18n.t("site_settings.errors.discourse_connect_url_is_empty"),
) )
end end
@ -29,13 +29,13 @@ RSpec.describe EnableSsoValidator do
describe "when value is false" do describe "when value is false" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
end end
end end
describe "when value is true" do describe "when value is true" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("t")).to eq(true) expect(validator.valid_value?("t")).to eq(true)
end end
end end
end end
@ -46,13 +46,13 @@ RSpec.describe EnableSsoValidator do
it "should be invalid" do it "should be invalid" do
SiteSetting.enforce_second_factor = "all" SiteSetting.enforce_second_factor = "all"
expect(subject.valid_value?("t")).to eq(false) expect(validator.valid_value?("t")).to eq(false)
end end
it "should be valid" do it "should be valid" do
SiteSetting.enforce_second_factor = "no" SiteSetting.enforce_second_factor = "no"
expect(subject.valid_value?("t")).to eq(true) expect(validator.valid_value?("t")).to eq(true)
end end
end end
end end

View File

@ -1,25 +1,25 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe ExternalSystemAvatarsValidator do RSpec.describe ExternalSystemAvatarsValidator do
subject { described_class.new } subject(:validator) { described_class.new }
it "disallows disabling external system avatars when Unicode usernames are enabled" do it "disallows disabling external system avatars when Unicode usernames are enabled" do
SiteSetting.unicode_usernames = true SiteSetting.unicode_usernames = true
expect(subject.valid_value?("f")).to eq(false) expect(validator.valid_value?("f")).to eq(false)
expect(subject.error_message).to eq(I18n.t("site_settings.errors.unicode_usernames_avatars")) expect(validator.error_message).to eq(I18n.t("site_settings.errors.unicode_usernames_avatars"))
expect(subject.valid_value?("t")).to eq(true) expect(validator.valid_value?("t")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
end end
it "allows disabling external system avatars when Unicode usernames are disabled" do it "allows disabling external system avatars when Unicode usernames are disabled" do
SiteSetting.unicode_usernames = false SiteSetting.unicode_usernames = false
expect(subject.valid_value?("t")).to eq(true) expect(validator.valid_value?("t")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
end end
end end

View File

@ -1,9 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe IpAddressFormatValidator do RSpec.describe IpAddressFormatValidator do
subject(:validate) { validator.validate_each(record, :ip_address, record.ip_address) }
let(:record) { Fabricate.build(:screened_ip_address, ip_address: "99.232.23.123") } let(:record) { Fabricate.build(:screened_ip_address, ip_address: "99.232.23.123") }
let(:validator) { described_class.new(attributes: :ip_address) } let(:validator) { described_class.new(attributes: :ip_address) }
subject(:validate) { validator.validate_each(record, :ip_address, record.ip_address) }
%w[99.232.23.123 99.232.0.0/16 fd12:db8::ff00:42:8329 fc00::/7].each do |arg| %w[99.232.23.123 99.232.0.0/16 fd12:db8::ff00:42:8329 fc00::/7].each do |arg|
it "should not add an error for #{arg}" do it "should not add an error for #{arg}" do

View File

@ -5,9 +5,10 @@ RSpec.describe PasswordValidator do
I18n.t("activerecord.errors.models.user.attributes.password.#{key.to_s}") I18n.t("activerecord.errors.models.user.attributes.password.#{key.to_s}")
end end
let(:validator) { described_class.new(attributes: :password) }
subject(:validate) { validator.validate_each(record, :password, @password) } subject(:validate) { validator.validate_each(record, :password, @password) }
let(:validator) { described_class.new(attributes: :password) }
describe "password required" do describe "password required" do
let(:record) do let(:record) do
u = Fabricate.build(:user, password: @password) u = Fabricate.build(:user, password: @password)

View File

@ -1,28 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe RegexPresenceValidator do RSpec.describe RegexPresenceValidator do
subject do subject(:validator) do
described_class.new(regex: "latest", regex_error: "site_settings.errors.must_include_latest") described_class.new(regex: "latest", regex_error: "site_settings.errors.must_include_latest")
end end
describe "#valid_value?" do describe "#valid_value?" do
describe "when value is present" do describe "when value is present" do
it "without regex match" do it "without regex match" do
expect(subject.valid_value?("categories|new")).to eq(false) expect(validator.valid_value?("categories|new")).to eq(false)
expect(subject.error_message).to eq(I18n.t("site_settings.errors.must_include_latest")) expect(validator.error_message).to eq(I18n.t("site_settings.errors.must_include_latest"))
end end
it "with regex match" do it "with regex match" do
expect(subject.valid_value?("latest|categories")).to eq(true) expect(validator.valid_value?("latest|categories")).to eq(true)
end end
end end
describe "when value is empty" do describe "when value is empty" do
it "should not be valid" do it "should not be valid" do
expect(subject.valid_value?("")).to eq(false) expect(validator.valid_value?("")).to eq(false)
expect(subject.error_message).to eq(I18n.t("site_settings.errors.must_include_latest")) expect(validator.error_message).to eq(I18n.t("site_settings.errors.must_include_latest"))
end end
end end
end end

View File

@ -1,15 +1,15 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe RegexpListValidator do RSpec.describe RegexpListValidator do
subject { described_class.new } subject(:validator) { described_class.new }
it "allows lists of valid regular expressions" do it "allows lists of valid regular expressions" do
expect(subject.valid_value?('\d+|[0-9]?|\w+')).to eq(true) expect(validator.valid_value?('\d+|[0-9]?|\w+')).to eq(true)
end end
it "does not allow lists of invalid regular expressions do" do it "does not allow lists of invalid regular expressions do" do
expect(subject.valid_value?('\d+|[0-9?|\w+')).to eq(false) expect(validator.valid_value?('\d+|[0-9?|\w+')).to eq(false)
expect(subject.error_message).to eq( expect(validator.error_message).to eq(
I18n.t( I18n.t(
"site_settings.errors.invalid_regex_with_message", "site_settings.errors.invalid_regex_with_message",
regex: "[0-9?", regex: "[0-9?",

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe SsoOverridesEmailValidator do RSpec.describe SsoOverridesEmailValidator do
subject { described_class.new } subject(:validator) { described_class.new }
describe "#valid_value?" do describe "#valid_value?" do
describe "when 'email editable' is true" do describe "when 'email editable' is true" do
@ -13,15 +13,17 @@ RSpec.describe SsoOverridesEmailValidator do
describe "when val is false" do describe "when val is false" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
end end
end end
describe "when value is true" do describe "when value is true" do
it "should not be valid" do it "should not be valid" do
expect(subject.valid_value?("t")).to eq(false) expect(validator.valid_value?("t")).to eq(false)
expect(subject.error_message).to eq(I18n.t("site_settings.errors.email_editable_enabled")) expect(validator.error_message).to eq(
I18n.t("site_settings.errors.email_editable_enabled"),
)
end end
end end
end end
@ -35,13 +37,13 @@ RSpec.describe SsoOverridesEmailValidator do
describe "when value is false" do describe "when value is false" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
end end
end end
describe "when value is true" do describe "when value is true" do
it "should be valid" do it "should be valid" do
expect(subject.valid_value?("t")).to eq(true) expect(validator.valid_value?("t")).to eq(true)
end end
end end
end end

View File

@ -1,37 +1,37 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe UnicodeUsernameAllowlistValidator do RSpec.describe UnicodeUsernameAllowlistValidator do
subject { described_class.new } subject(:validator) { described_class.new }
it "allows an empty allowlist" do it "allows an empty allowlist" do
expect(subject.valid_value?("")).to eq(true) expect(validator.valid_value?("")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
end end
it "disallows leading and trailing slashes" do it "disallows leading and trailing slashes" do
expected_error = I18n.t("site_settings.errors.allowed_unicode_usernames.leading_trailing_slash") expected_error = I18n.t("site_settings.errors.allowed_unicode_usernames.leading_trailing_slash")
expect(subject.valid_value?("/foo/")).to eq(false) expect(validator.valid_value?("/foo/")).to eq(false)
expect(subject.error_message).to eq(expected_error) expect(validator.error_message).to eq(expected_error)
expect(subject.valid_value?("foo/")).to eq(true) expect(validator.valid_value?("foo/")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
expect(subject.valid_value?("/foo")).to eq(true) expect(validator.valid_value?("/foo")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
expect(subject.valid_value?("f/o/o")).to eq(true) expect(validator.valid_value?("f/o/o")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
expect(subject.valid_value?("/foo/i")).to eq(false) expect(validator.valid_value?("/foo/i")).to eq(false)
expect(subject.error_message).to eq(expected_error) expect(validator.error_message).to eq(expected_error)
end end
it "detects invalid regular expressions" do it "detects invalid regular expressions" do
expected_error = expected_error =
I18n.t("site_settings.errors.allowed_unicode_usernames.regex_invalid", error: "") I18n.t("site_settings.errors.allowed_unicode_usernames.regex_invalid", error: "")
expect(subject.valid_value?("\\p{Foo}")).to eq(false) expect(validator.valid_value?("\\p{Foo}")).to eq(false)
expect(subject.error_message).to start_with(expected_error) expect(validator.error_message).to start_with(expected_error)
end end
end end

View File

@ -1,25 +1,25 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe UnicodeUsernameValidator do RSpec.describe UnicodeUsernameValidator do
subject { described_class.new } subject(:validator) { described_class.new }
it "disallows Unicode usernames when external system avatars are disabled" do it "disallows Unicode usernames when external system avatars are disabled" do
SiteSetting.external_system_avatars_enabled = false SiteSetting.external_system_avatars_enabled = false
expect(subject.valid_value?("t")).to eq(false) expect(validator.valid_value?("t")).to eq(false)
expect(subject.error_message).to eq(I18n.t("site_settings.errors.unicode_usernames_avatars")) expect(validator.error_message).to eq(I18n.t("site_settings.errors.unicode_usernames_avatars"))
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
end end
it "allows Unicode usernames when external system avatars are enabled" do it "allows Unicode usernames when external system avatars are enabled" do
SiteSetting.external_system_avatars_enabled = true SiteSetting.external_system_avatars_enabled = true
expect(subject.valid_value?("t")).to eq(true) expect(validator.valid_value?("t")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
expect(subject.valid_value?("f")).to eq(true) expect(validator.valid_value?("f")).to eq(true)
expect(subject.error_message).to be_blank expect(validator.error_message).to be_blank
end end
end end

View File

@ -45,7 +45,7 @@ RSpec.describe UploadValidator do
original_filename: "test.png", original_filename: "test.png",
filesize: 2_097_152, filesize: 2_097_152,
) )
subject.validate(upload) validator.validate(upload)
expect(upload.errors.full_messages.first).to eq( expect(upload.errors.full_messages.first).to eq(
"Filesize #{I18n.t("upload.images.too_large_humanized", max_size: "1.5 MB")}", "Filesize #{I18n.t("upload.images.too_large_humanized", max_size: "1.5 MB")}",
) )
@ -62,7 +62,7 @@ RSpec.describe UploadValidator do
for_private_message: true, for_private_message: true,
) )
expect(subject.validate(upload)).to eq(true) expect(validator.validate(upload)).to eq(true)
end end
describe "for a normal user" do describe "for a normal user" do
@ -75,7 +75,7 @@ RSpec.describe UploadValidator do
for_private_message: true, for_private_message: true,
) )
expect(subject.validate(upload)).to eq(nil) expect(validator.validate(upload)).to eq(nil)
end end
end end
end end
@ -91,13 +91,13 @@ RSpec.describe UploadValidator do
describe "for admin user" do describe "for admin user" do
it "should allow the upload" do it "should allow the upload" do
expect(subject.validate(upload)).to eq(true) expect(validator.validate(upload)).to eq(true)
end end
describe "when filename is invalid" do describe "when filename is invalid" do
it "should not allow the upload" do it "should not allow the upload" do
upload.original_filename = "test.txt" upload.original_filename = "test.txt"
expect(subject.validate(upload)).to eq(nil) expect(validator.validate(upload)).to eq(nil)
end end
end end
end end
@ -106,7 +106,7 @@ RSpec.describe UploadValidator do
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
it "should not allow the upload" do it "should not allow the upload" do
expect(subject.validate(upload)).to eq(nil) expect(validator.validate(upload)).to eq(nil)
end end
end end
end end

View File

@ -1,9 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe UrlValidator do RSpec.describe UrlValidator do
subject(:validate) { validator.validate_each(record, :website, record.website) }
let(:record) { Fabricate.build(:user_profile, user: Fabricate.build(:user)) } let(:record) { Fabricate.build(:user_profile, user: Fabricate.build(:user)) }
let(:validator) { described_class.new(attributes: :website) } let(:validator) { described_class.new(attributes: :website) }
subject(:validate) { validator.validate_each(record, :website, record.website) }
[ [
"http://https://google.com", "http://https://google.com",

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe UserFullNameValidator do RSpec.describe UserFullNameValidator do
let(:validator) { described_class.new(attributes: :name) }
subject(:validate) { validator.validate_each(record, :name, @name) } subject(:validate) { validator.validate_each(record, :name, @name) }
let(:validator) { described_class.new(attributes: :name) }
let(:record) { Fabricate.build(:user, name: @name) } let(:record) { Fabricate.build(:user, name: @name) }
context "when name is not required" do context "when name is not required" do

View File

@ -38,6 +38,8 @@ require "webauthn/security_key_registration_service"
# The origin params just need to be whatever your localhost URL for Discourse is. # The origin params just need to be whatever your localhost URL for Discourse is.
RSpec.describe Webauthn::SecurityKeyAuthenticationService do RSpec.describe Webauthn::SecurityKeyAuthenticationService do
subject(:service) { described_class.new(current_user, params, challenge_params) }
let(:security_key_user) { current_user } let(:security_key_user) { current_user }
let!(:security_key) do let!(:security_key) do
Fabricate( Fabricate(
@ -91,24 +93,23 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
let(:challenge_params_origin) { "http://localhost:3000" } let(:challenge_params_origin) { "http://localhost:3000" }
let(:challenge_params) { { challenge: challenge, rp_id: rp_id, origin: challenge_params_origin } } let(:challenge_params) { { challenge: challenge, rp_id: rp_id, origin: challenge_params_origin } }
let(:current_user) { Fabricate(:user) } let(:current_user) { Fabricate(:user) }
let(:subject) { described_class.new(current_user, params, challenge_params) }
it "updates last_used when the security key and params are valid" do it "updates last_used when the security key and params are valid" do
expect(subject.authenticate_security_key).to eq(true) expect(service.authenticate_security_key).to eq(true)
expect(security_key.reload.last_used).not_to eq(nil) expect(security_key.reload.last_used).not_to eq(nil)
end end
context "when params is blank" do context "when params is blank" do
let(:params) { nil } let(:params) { nil }
it "returns false with no validation" do it "returns false with no validation" do
expect(subject.authenticate_security_key).to eq(false) expect(service.authenticate_security_key).to eq(false)
end end
end end
context "when params is not blank and not a hash" do context "when params is not blank and not a hash" do
let(:params) { "test" } let(:params) { "test" }
it "returns false with no validation" do it "returns false with no validation" do
expect(subject.authenticate_security_key).to eq(false) expect(service.authenticate_security_key).to eq(false)
end end
end end
@ -116,7 +117,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
before { security_key.destroy } before { security_key.destroy }
it "raises a NotFoundError" do it "raises a NotFoundError" do
expect { subject.authenticate_security_key }.to raise_error( expect { service.authenticate_security_key }.to raise_error(
Webauthn::NotFoundError, Webauthn::NotFoundError,
I18n.t("webauthn.validation.not_found_error"), I18n.t("webauthn.validation.not_found_error"),
) )
@ -127,7 +128,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
let(:security_key_user) { Fabricate(:user) } let(:security_key_user) { Fabricate(:user) }
it "raises an OwnershipError" do it "raises an OwnershipError" do
expect { subject.authenticate_security_key }.to raise_error( expect { service.authenticate_security_key }.to raise_error(
Webauthn::OwnershipError, Webauthn::OwnershipError,
I18n.t("webauthn.validation.ownership_error"), I18n.t("webauthn.validation.ownership_error"),
) )
@ -138,7 +139,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
let(:client_data_webauthn_type) { "webauthn.explode" } let(:client_data_webauthn_type) { "webauthn.explode" }
it "raises an InvalidTypeError" do it "raises an InvalidTypeError" do
expect { subject.authenticate_security_key }.to raise_error( expect { service.authenticate_security_key }.to raise_error(
Webauthn::InvalidTypeError, Webauthn::InvalidTypeError,
I18n.t("webauthn.validation.invalid_type_error"), I18n.t("webauthn.validation.invalid_type_error"),
) )
@ -149,7 +150,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
let(:client_data_challenge) { Base64.strict_encode64("invalid challenge") } let(:client_data_challenge) { Base64.strict_encode64("invalid challenge") }
it "raises a ChallengeMismatchError" do it "raises a ChallengeMismatchError" do
expect { subject.authenticate_security_key }.to raise_error( expect { service.authenticate_security_key }.to raise_error(
Webauthn::ChallengeMismatchError, Webauthn::ChallengeMismatchError,
I18n.t("webauthn.validation.challenge_mismatch_error"), I18n.t("webauthn.validation.challenge_mismatch_error"),
) )
@ -160,7 +161,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
let(:client_data_origin) { "https://someothersite.com" } let(:client_data_origin) { "https://someothersite.com" }
it "raises a InvalidOriginError" do it "raises a InvalidOriginError" do
expect { subject.authenticate_security_key }.to raise_error( expect { service.authenticate_security_key }.to raise_error(
Webauthn::InvalidOriginError, Webauthn::InvalidOriginError,
I18n.t("webauthn.validation.invalid_origin_error"), I18n.t("webauthn.validation.invalid_origin_error"),
) )
@ -171,7 +172,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
let(:rp_id) { "bad_rp_id" } let(:rp_id) { "bad_rp_id" }
it "raises a InvalidRelyingPartyIdError" do it "raises a InvalidRelyingPartyIdError" do
expect { subject.authenticate_security_key }.to raise_error( expect { service.authenticate_security_key }.to raise_error(
Webauthn::InvalidRelyingPartyIdError, Webauthn::InvalidRelyingPartyIdError,
I18n.t("webauthn.validation.invalid_relying_party_id_error"), I18n.t("webauthn.validation.invalid_relying_party_id_error"),
) )
@ -182,7 +183,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
let(:signature) { Base64.strict_encode64("badsig") } let(:signature) { Base64.strict_encode64("badsig") }
it "raises a PublicKeyError" do it "raises a PublicKeyError" do
expect { subject.authenticate_security_key }.to raise_error( expect { service.authenticate_security_key }.to raise_error(
Webauthn::PublicKeyError, Webauthn::PublicKeyError,
I18n.t("webauthn.validation.public_key_error"), I18n.t("webauthn.validation.public_key_error"),
) )
@ -193,7 +194,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
before { COSE::Algorithm.expects(:find).returns(nil) } before { COSE::Algorithm.expects(:find).returns(nil) }
it "raises a UnknownCOSEAlgorithmError" do it "raises a UnknownCOSEAlgorithmError" do
expect { subject.authenticate_security_key }.to raise_error( expect { service.authenticate_security_key }.to raise_error(
Webauthn::UnknownCOSEAlgorithmError, Webauthn::UnknownCOSEAlgorithmError,
I18n.t("webauthn.validation.unknown_cose_algorithm_error"), I18n.t("webauthn.validation.unknown_cose_algorithm_error"),
) )
@ -230,7 +231,7 @@ RSpec.describe Webauthn::SecurityKeyAuthenticationService do
end end
it "updates last_used when the security key and params are valid" do it "updates last_used when the security key and params are valid" do
expect(subject.authenticate_security_key).to eq(true) expect(service.authenticate_security_key).to eq(true)
expect(security_key.reload.last_used).not_to eq(nil) expect(security_key.reload.last_used).not_to eq(nil)
end end
end end

View File

@ -3,6 +3,8 @@ require "webauthn"
require "webauthn/security_key_registration_service" require "webauthn/security_key_registration_service"
RSpec.describe Webauthn::SecurityKeyRegistrationService do RSpec.describe Webauthn::SecurityKeyRegistrationService do
subject(:service) { described_class.new(current_user, params, challenge_params) }
let(:client_data_challenge) { Base64.encode64(challenge) } let(:client_data_challenge) { Base64.encode64(challenge) }
let(:client_data_webauthn_type) { "webauthn.create" } let(:client_data_webauthn_type) { "webauthn.create" }
let(:client_data_origin) { "http://localhost:3000" } let(:client_data_origin) { "http://localhost:3000" }
@ -34,13 +36,12 @@ RSpec.describe Webauthn::SecurityKeyRegistrationService do
let(:challenge_params) { { challenge: challenge, rp_id: rp_id, origin: "http://localhost:3000" } } let(:challenge_params) { { challenge: challenge, rp_id: rp_id, origin: "http://localhost:3000" } }
let(:challenge) { "f1e04530f34a1b6a08d032d8550e23eb8330be04e4166008f26c0e1b42ad" } let(:challenge) { "f1e04530f34a1b6a08d032d8550e23eb8330be04e4166008f26c0e1b42ad" }
let(:current_user) { Fabricate(:user) } let(:current_user) { Fabricate(:user) }
let(:subject) { described_class.new(current_user, params, challenge_params) }
context "when the client data webauthn type is not webauthn.create" do context "when the client data webauthn type is not webauthn.create" do
let(:client_data_webauthn_type) { "webauthn.explode" } let(:client_data_webauthn_type) { "webauthn.explode" }
it "raises an InvalidTypeError" do it "raises an InvalidTypeError" do
expect { subject.register_second_factor_security_key }.to raise_error( expect { service.register_second_factor_security_key }.to raise_error(
Webauthn::InvalidTypeError, Webauthn::InvalidTypeError,
I18n.t("webauthn.validation.invalid_type_error"), I18n.t("webauthn.validation.invalid_type_error"),
) )
@ -51,7 +52,7 @@ RSpec.describe Webauthn::SecurityKeyRegistrationService do
let(:client_data_challenge) { Base64.encode64("invalid challenge") } let(:client_data_challenge) { Base64.encode64("invalid challenge") }
it "raises a ChallengeMismatchError" do it "raises a ChallengeMismatchError" do
expect { subject.register_second_factor_security_key }.to raise_error( expect { service.register_second_factor_security_key }.to raise_error(
Webauthn::ChallengeMismatchError, Webauthn::ChallengeMismatchError,
I18n.t("webauthn.validation.challenge_mismatch_error"), I18n.t("webauthn.validation.challenge_mismatch_error"),
) )
@ -62,7 +63,7 @@ RSpec.describe Webauthn::SecurityKeyRegistrationService do
let(:client_data_origin) { "https://someothersite.com" } let(:client_data_origin) { "https://someothersite.com" }
it "raises a InvalidOriginError" do it "raises a InvalidOriginError" do
expect { subject.register_second_factor_security_key }.to raise_error( expect { service.register_second_factor_security_key }.to raise_error(
Webauthn::InvalidOriginError, Webauthn::InvalidOriginError,
I18n.t("webauthn.validation.invalid_origin_error"), I18n.t("webauthn.validation.invalid_origin_error"),
) )
@ -73,7 +74,7 @@ RSpec.describe Webauthn::SecurityKeyRegistrationService do
let(:rp_id) { "bad_rp_id" } let(:rp_id) { "bad_rp_id" }
it "raises a InvalidRelyingPartyIdError" do it "raises a InvalidRelyingPartyIdError" do
expect { subject.register_second_factor_security_key }.to raise_error( expect { service.register_second_factor_security_key }.to raise_error(
Webauthn::InvalidRelyingPartyIdError, Webauthn::InvalidRelyingPartyIdError,
I18n.t("webauthn.validation.invalid_relying_party_id_error"), I18n.t("webauthn.validation.invalid_relying_party_id_error"),
) )
@ -87,7 +88,7 @@ RSpec.describe Webauthn::SecurityKeyRegistrationService do
end end
it "raises a UnsupportedPublicKeyAlgorithmError" do it "raises a UnsupportedPublicKeyAlgorithmError" do
expect { subject.register_second_factor_security_key }.to raise_error( expect { service.register_second_factor_security_key }.to raise_error(
Webauthn::UnsupportedPublicKeyAlgorithmError, Webauthn::UnsupportedPublicKeyAlgorithmError,
I18n.t("webauthn.validation.unsupported_public_key_algorithm_error"), I18n.t("webauthn.validation.unsupported_public_key_algorithm_error"),
) )
@ -103,7 +104,7 @@ RSpec.describe Webauthn::SecurityKeyRegistrationService do
end end
it "raises a UnsupportedAttestationFormatError" do it "raises a UnsupportedAttestationFormatError" do
expect { subject.register_second_factor_security_key }.to raise_error( expect { service.register_second_factor_security_key }.to raise_error(
Webauthn::UnsupportedAttestationFormatError, Webauthn::UnsupportedAttestationFormatError,
I18n.t("webauthn.validation.unsupported_attestation_format_error"), I18n.t("webauthn.validation.unsupported_attestation_format_error"),
) )
@ -117,14 +118,14 @@ RSpec.describe Webauthn::SecurityKeyRegistrationService do
context "when the credential id is already in use for any user" do context "when the credential id is already in use for any user" do
it "raises a CredentialIdInUseError" do it "raises a CredentialIdInUseError" do
# register the key to the current user # register the key to the current user
security_key = subject.register_second_factor_security_key security_key = service.register_second_factor_security_key
# update the key to be on a different user # update the key to be on a different user
other_user = Fabricate(:user) other_user = Fabricate(:user)
security_key.update(user: other_user) security_key.update(user: other_user)
# error! # error!
expect { subject.register_second_factor_security_key }.to raise_error( expect { service.register_second_factor_security_key }.to raise_error(
Webauthn::CredentialIdInUseError, Webauthn::CredentialIdInUseError,
I18n.t("webauthn.validation.credential_id_in_use_error"), I18n.t("webauthn.validation.credential_id_in_use_error"),
) )
@ -137,7 +138,7 @@ RSpec.describe Webauthn::SecurityKeyRegistrationService do
end end
it "raises a MalformedAttestationError" do it "raises a MalformedAttestationError" do
expect { subject.register_second_factor_security_key }.to raise_error( expect { service.register_second_factor_security_key }.to raise_error(
Webauthn::MalformedAttestationError, Webauthn::MalformedAttestationError,
I18n.t("webauthn.validation.malformed_attestation_error"), I18n.t("webauthn.validation.malformed_attestation_error"),
) )

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe SubscriptionMailer do RSpec.describe SubscriptionMailer do
subject(:mail) { SubscriptionMailer.confirm_unsubscribe(user) }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
subject { SubscriptionMailer.confirm_unsubscribe(user) }
it "contains the right URL" do it "contains the right URL" do
expect(subject.body).to include( expect(mail.body).to include(
"#{Discourse.base_url}/email/unsubscribe/#{UnsubscribeKey.last.key}", "#{Discourse.base_url}/email/unsubscribe/#{UnsubscribeKey.last.key}",
) )
end end

View File

@ -58,24 +58,24 @@ RSpec.describe UserNotifications do
end end
describe ".signup" do describe ".signup" do
subject { UserNotifications.signup(user) } subject(:email) { UserNotifications.signup(user) }
it "works" do it "works" do
expect(subject.to).to eq([user.email]) expect(email.to).to eq([user.email])
expect(subject.subject).to be_present expect(email.subject).to be_present
expect(subject.from).to eq([SiteSetting.notification_email]) expect(email.from).to eq([SiteSetting.notification_email])
expect(subject.body).to be_present expect(email.body).to be_present
end end
end end
describe ".forgot_password" do describe ".forgot_password" do
subject { UserNotifications.forgot_password(user) } subject(:email) { UserNotifications.forgot_password(user) }
it "works" do it "works" do
expect(subject.to).to eq([user.email]) expect(email.to).to eq([user.email])
expect(subject.subject).to be_present expect(email.subject).to be_present
expect(subject.from).to eq([SiteSetting.notification_email]) expect(email.from).to eq([SiteSetting.notification_email])
expect(subject.body).to be_present expect(email.body).to be_present
end end
end end
@ -119,20 +119,21 @@ RSpec.describe UserNotifications do
end end
describe ".email_login" do describe ".email_login" do
subject(:email) { UserNotifications.email_login(user, email_token: email_token) }
let(:email_token) do let(:email_token) do
Fabricate(:email_token, user: user, scope: EmailToken.scopes[:email_login]).token Fabricate(:email_token, user: user, scope: EmailToken.scopes[:email_login]).token
end end
subject { UserNotifications.email_login(user, email_token: email_token) }
it "generates the right email" do it "generates the right email" do
expect(subject.to).to eq([user.email]) expect(email.to).to eq([user.email])
expect(subject.from).to eq([SiteSetting.notification_email]) expect(email.from).to eq([SiteSetting.notification_email])
expect(subject.subject).to eq( expect(email.subject).to eq(
I18n.t("user_notifications.email_login.subject_template", email_prefix: SiteSetting.title), I18n.t("user_notifications.email_login.subject_template", email_prefix: SiteSetting.title),
) )
expect(subject.body.to_s).to match( expect(email.body.to_s).to match(
I18n.t( I18n.t(
"user_notifications.email_login.text_body_template", "user_notifications.email_login.text_body_template",
site_name: SiteSetting.title, site_name: SiteSetting.title,
@ -144,13 +145,13 @@ RSpec.describe UserNotifications do
end end
describe ".digest" do describe ".digest" do
subject { UserNotifications.digest(user) } subject(:email) { UserNotifications.digest(user) }
after { Discourse.redis.keys("summary-new-users:*").each { |key| Discourse.redis.del(key) } } after { Discourse.redis.keys("summary-new-users:*").each { |key| Discourse.redis.del(key) } }
context "without new topics" do context "without new topics" do
it "doesn't send the email" do it "doesn't send the email" do
expect(subject.to).to be_blank expect(email.to).to be_blank
end end
end end
@ -172,8 +173,8 @@ RSpec.describe UserNotifications do
end end
it "returns topics from new users if they're more than 24 hours old" do it "returns topics from new users if they're more than 24 hours old" do
expect(subject.to).to eq([user.email]) expect(email.to).to eq([user.email])
html = subject.html_part.body.to_s html = email.html_part.body.to_s
expect(html).to include(new_yesterday.title) expect(html).to include(new_yesterday.title)
expect(html).to_not include(new_today.title) expect(html).to_not include(new_today.title)
end end
@ -185,18 +186,18 @@ RSpec.describe UserNotifications do
end end
it "works" do it "works" do
expect(subject.to).to eq([user.email]) expect(email.to).to eq([user.email])
expect(subject.subject).to be_present expect(email.subject).to be_present
expect(subject.from).to eq([SiteSetting.notification_email]) expect(email.from).to eq([SiteSetting.notification_email])
expect(subject.html_part.body.to_s).to be_present expect(email.html_part.body.to_s).to be_present
expect(subject.text_part.body.to_s).to be_present expect(email.text_part.body.to_s).to be_present
expect(subject.header["List-Unsubscribe"].to_s).to match(/\/email\/unsubscribe\/\h{64}/) expect(email.header["List-Unsubscribe"].to_s).to match(/\/email\/unsubscribe\/\h{64}/)
expect(subject.html_part.body.to_s).to include("New Users") expect(email.html_part.body.to_s).to include("New Users")
end end
it "doesn't include new user count if digest_after_minutes is low" do it "doesn't include new user count if digest_after_minutes is low" do
user.user_option.digest_after_minutes = 60 user.user_option.digest_after_minutes = 60
expect(subject.html_part.body.to_s).to_not include("New Users") expect(email.html_part.body.to_s).to_not include("New Users")
end end
it "works with min_date string" do it "works with min_date string" do
@ -210,8 +211,8 @@ RSpec.describe UserNotifications do
SiteSetting.email_prefix = "Try Discourse" SiteSetting.email_prefix = "Try Discourse"
SiteSetting.title = "Discourse Meta" SiteSetting.title = "Discourse Meta"
expect(subject.subject).to match(/Try Discourse/) expect(email.subject).to match(/Try Discourse/)
expect(subject.subject).not_to match(/Discourse Meta/) expect(email.subject).not_to match(/Discourse Meta/)
end end
it "includes unread likes received count within the since date" do it "includes unread likes received count within the since date" do
@ -257,7 +258,7 @@ RSpec.describe UserNotifications do
created_at: 1.hour.ago, created_at: 1.hour.ago,
) )
deleted.trash! deleted.trash!
html = subject.html_part.body.to_s html = email.html_part.body.to_s
expect(html).to_not include deleted.title expect(html).to_not include deleted.title
expect(html).to_not include post.raw expect(html).to_not include post.raw
end end
@ -276,7 +277,7 @@ RSpec.describe UserNotifications do
raw: "secret draft content", raw: "secret draft content",
created_at: 1.hour.ago, created_at: 1.hour.ago,
) )
html = subject.html_part.body.to_s html = email.html_part.body.to_s
expect(html).to_not include topic.title expect(html).to_not include topic.title
expect(html).to_not include post.raw expect(html).to_not include post.raw
end end
@ -319,7 +320,7 @@ RSpec.describe UserNotifications do
post_type: Post.types[:small_action], post_type: Post.types[:small_action],
created_at: 1.hour.ago, created_at: 1.hour.ago,
) )
html = subject.html_part.body.to_s html = email.html_part.body.to_s
expect(html).to_not include whisper.raw expect(html).to_not include whisper.raw
expect(html).to_not include mod_action.raw expect(html).to_not include mod_action.raw
expect(html).to_not include small_action.raw expect(html).to_not include small_action.raw
@ -365,7 +366,7 @@ RSpec.describe UserNotifications do
user_deleted: true, user_deleted: true,
created_at: 1.hour.ago, created_at: 1.hour.ago,
) )
html = subject.html_part.body.to_s html = email.html_part.body.to_s
expect(html).to_not include deleted.raw expect(html).to_not include deleted.raw
expect(html).to_not include hidden.raw expect(html).to_not include hidden.raw
expect(html).to_not include user_deleted.raw expect(html).to_not include user_deleted.raw
@ -389,7 +390,7 @@ RSpec.describe UserNotifications do
post_number: 1, post_number: 1,
created_at: 1.minute.ago, created_at: 1.minute.ago,
) )
html = subject.html_part.body.to_s html = email.html_part.body.to_s
expect(html).to_not include too_new.title expect(html).to_not include too_new.title
end end
@ -408,20 +409,20 @@ RSpec.describe UserNotifications do
theme.set_default! theme.set_default!
html = subject.html_part.body.to_s html = email.html_part.body.to_s
expect(html).to include "F0F0F0" expect(html).to include "F0F0F0"
expect(html).to include "1E1E1E" expect(html).to include "1E1E1E"
end end
it "supports subfolder" do it "supports subfolder" do
set_subfolder "/forum" set_subfolder "/forum"
html = subject.html_part.body.to_s html = email.html_part.body.to_s
text = subject.text_part.body.to_s text = email.text_part.body.to_s
expect(html).to be_present expect(html).to be_present
expect(text).to be_present expect(text).to be_present
expect(html).to_not include("/forum/forum") expect(html).to_not include("/forum/forum")
expect(text).to_not include("/forum/forum") expect(text).to_not include("/forum/forum")
expect(subject.header["List-Unsubscribe"].to_s).to match( expect(email.header["List-Unsubscribe"].to_s).to match(
/http:\/\/test.localhost\/forum\/email\/unsubscribe\/\h{64}/, /http:\/\/test.localhost\/forum\/email\/unsubscribe\/\h{64}/,
) )
@ -432,7 +433,7 @@ RSpec.describe UserNotifications do
it "applies lang/xml:lang html attributes" do it "applies lang/xml:lang html attributes" do
SiteSetting.default_locale = "pl_PL" SiteSetting.default_locale = "pl_PL"
html = subject.html_part.to_s html = email.html_part.to_s
expect(html).to match(' lang="pl-PL"') expect(html).to match(' lang="pl-PL"')
expect(html).to match(' xml:lang="pl-PL"') expect(html).to match(' xml:lang="pl-PL"')

View File

@ -1,13 +1,13 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe VersionMailer do RSpec.describe VersionMailer do
subject { VersionMailer.send_notice } subject(:mail) { VersionMailer.send_notice }
context "when contact_email is blank" do context "when contact_email is blank" do
before { SiteSetting.contact_email = "" } before { SiteSetting.contact_email = "" }
it "doesn't send the email" do it "doesn't send the email" do
expect(subject.to).to be_blank expect(mail.to).to be_blank
end end
end end
@ -15,10 +15,10 @@ RSpec.describe VersionMailer do
before { SiteSetting.contact_email = "me@example.com" } before { SiteSetting.contact_email = "me@example.com" }
it "works" do it "works" do
expect(subject.to).to eq(["me@example.com"]) expect(mail.to).to eq(["me@example.com"])
expect(subject.subject).to be_present expect(mail.subject).to be_present
expect(subject.from).to eq([SiteSetting.notification_email]) expect(mail.from).to eq([SiteSetting.notification_email])
expect(subject.body).to be_present expect(mail.body).to be_present
end end
end end
end end

View File

@ -126,93 +126,93 @@ RSpec.describe AdminDashboardData do
end end
describe "rails_env_check" do describe "rails_env_check" do
subject { described_class.new.rails_env_check } subject(:check) { described_class.new.rails_env_check }
it "returns nil when running in production mode" do it "returns nil when running in production mode" do
Rails.stubs(env: ActiveSupport::StringInquirer.new("production")) Rails.stubs(env: ActiveSupport::StringInquirer.new("production"))
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns a string when running in development mode" do it "returns a string when running in development mode" do
Rails.stubs(env: ActiveSupport::StringInquirer.new("development")) Rails.stubs(env: ActiveSupport::StringInquirer.new("development"))
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
it "returns a string when running in test mode" do it "returns a string when running in test mode" do
Rails.stubs(env: ActiveSupport::StringInquirer.new("test")) Rails.stubs(env: ActiveSupport::StringInquirer.new("test"))
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
end end
describe "host_names_check" do describe "host_names_check" do
subject { described_class.new.host_names_check } subject(:check) { described_class.new.host_names_check }
it "returns nil when host_names is set" do it "returns nil when host_names is set" do
Discourse.stubs(:current_hostname).returns("something.com") Discourse.stubs(:current_hostname).returns("something.com")
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns a string when host_name is localhost" do it "returns a string when host_name is localhost" do
Discourse.stubs(:current_hostname).returns("localhost") Discourse.stubs(:current_hostname).returns("localhost")
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
it "returns a string when host_name is production.localhost" do it "returns a string when host_name is production.localhost" do
Discourse.stubs(:current_hostname).returns("production.localhost") Discourse.stubs(:current_hostname).returns("production.localhost")
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
end end
describe "sidekiq_check" do describe "sidekiq_check" do
subject { described_class.new.sidekiq_check } subject(:check) { described_class.new.sidekiq_check }
it "returns nil when sidekiq processed a job recently" do it "returns nil when sidekiq processed a job recently" do
Jobs.stubs(:last_job_performed_at).returns(1.minute.ago) Jobs.stubs(:last_job_performed_at).returns(1.minute.ago)
Jobs.stubs(:queued).returns(0) Jobs.stubs(:queued).returns(0)
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns nil when last job processed was a long time ago, but no jobs are queued" do it "returns nil when last job processed was a long time ago, but no jobs are queued" do
Jobs.stubs(:last_job_performed_at).returns(7.days.ago) Jobs.stubs(:last_job_performed_at).returns(7.days.ago)
Jobs.stubs(:queued).returns(0) Jobs.stubs(:queued).returns(0)
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns nil when no jobs have ever been processed, but no jobs are queued" do it "returns nil when no jobs have ever been processed, but no jobs are queued" do
Jobs.stubs(:last_job_performed_at).returns(nil) Jobs.stubs(:last_job_performed_at).returns(nil)
Jobs.stubs(:queued).returns(0) Jobs.stubs(:queued).returns(0)
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns a string when no jobs were processed recently and some jobs are queued" do it "returns a string when no jobs were processed recently and some jobs are queued" do
Jobs.stubs(:last_job_performed_at).returns(20.minutes.ago) Jobs.stubs(:last_job_performed_at).returns(20.minutes.ago)
Jobs.stubs(:queued).returns(1) Jobs.stubs(:queued).returns(1)
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
it "returns a string when no jobs have ever been processed, and some jobs are queued" do it "returns a string when no jobs have ever been processed, and some jobs are queued" do
Jobs.stubs(:last_job_performed_at).returns(nil) Jobs.stubs(:last_job_performed_at).returns(nil)
Jobs.stubs(:queued).returns(1) Jobs.stubs(:queued).returns(1)
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
end end
describe "ram_check" do describe "ram_check" do
subject { described_class.new.ram_check } subject(:check) { described_class.new.ram_check }
it "returns nil when total ram is 1 GB" do it "returns nil when total ram is 1 GB" do
MemInfo.any_instance.stubs(:mem_total).returns(1_025_272) MemInfo.any_instance.stubs(:mem_total).returns(1_025_272)
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns nil when total ram cannot be determined" do it "returns nil when total ram cannot be determined" do
MemInfo.any_instance.stubs(:mem_total).returns(nil) MemInfo.any_instance.stubs(:mem_total).returns(nil)
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns a string when total ram is less than 1 GB" do it "returns a string when total ram is less than 1 GB" do
MemInfo.any_instance.stubs(:mem_total).returns(512_636) MemInfo.any_instance.stubs(:mem_total).returns(512_636)
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
end end
@ -221,7 +221,7 @@ RSpec.describe AdminDashboardData do
context "when disabled" do context "when disabled" do
it "returns nil" do it "returns nil" do
SiteSetting.set(enable_setting, false) SiteSetting.set(enable_setting, false)
expect(subject).to be_nil expect(check).to be_nil
end end
end end
@ -231,31 +231,32 @@ RSpec.describe AdminDashboardData do
it "returns nil when key and secret are set" do it "returns nil when key and secret are set" do
SiteSetting.set(key, "12313213") SiteSetting.set(key, "12313213")
SiteSetting.set(secret, "12312313123") SiteSetting.set(secret, "12312313123")
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns a string when key is not set" do it "returns a string when key is not set" do
SiteSetting.set(key, "") SiteSetting.set(key, "")
SiteSetting.set(secret, "12312313123") SiteSetting.set(secret, "12312313123")
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
it "returns a string when secret is not set" do it "returns a string when secret is not set" do
SiteSetting.set(key, "123123") SiteSetting.set(key, "123123")
SiteSetting.set(secret, "") SiteSetting.set(secret, "")
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
it "returns a string when key and secret are not set" do it "returns a string when key and secret are not set" do
SiteSetting.set(key, "") SiteSetting.set(key, "")
SiteSetting.set(secret, "") SiteSetting.set(secret, "")
expect(subject).to_not be_nil expect(check).to_not be_nil
end end
end end
end end
describe "facebook" do describe "facebook" do
subject { described_class.new.facebook_config_check } subject(:check) { described_class.new.facebook_config_check }
let(:enable_setting) { :enable_facebook_logins } let(:enable_setting) { :enable_facebook_logins }
let(:key) { :facebook_app_id } let(:key) { :facebook_app_id }
let(:secret) { :facebook_app_secret } let(:secret) { :facebook_app_secret }
@ -263,7 +264,8 @@ RSpec.describe AdminDashboardData do
end end
describe "twitter" do describe "twitter" do
subject { described_class.new.twitter_config_check } subject(:check) { described_class.new.twitter_config_check }
let(:enable_setting) { :enable_twitter_logins } let(:enable_setting) { :enable_twitter_logins }
let(:key) { :twitter_consumer_key } let(:key) { :twitter_consumer_key }
let(:secret) { :twitter_consumer_secret } let(:secret) { :twitter_consumer_secret }
@ -271,7 +273,8 @@ RSpec.describe AdminDashboardData do
end end
describe "github" do describe "github" do
subject { described_class.new.github_config_check } subject(:check) { described_class.new.github_config_check }
let(:enable_setting) { :enable_github_logins } let(:enable_setting) { :enable_github_logins }
let(:key) { :github_client_id } let(:key) { :github_client_id }
let(:secret) { :github_client_secret } let(:secret) { :github_client_secret }
@ -280,28 +283,28 @@ RSpec.describe AdminDashboardData do
end end
describe "force_https_check" do describe "force_https_check" do
subject { described_class.new(check_force_https: true).force_https_check } subject(:check) { described_class.new(check_force_https: true).force_https_check }
it "returns nil if force_https site setting enabled" do it "returns nil if force_https site setting enabled" do
SiteSetting.force_https = true SiteSetting.force_https = true
expect(subject).to be_nil expect(check).to be_nil
end end
it "returns nil if force_https site setting not enabled" do it "returns nil if force_https site setting not enabled" do
SiteSetting.force_https = false SiteSetting.force_https = false
expect(subject).to eq(I18n.t("dashboard.force_https_warning", base_path: Discourse.base_path)) expect(check).to eq(I18n.t("dashboard.force_https_warning", base_path: Discourse.base_path))
end end
end end
describe "ignore force_https_check" do describe "ignore force_https_check" do
subject { described_class.new(check_force_https: false).force_https_check } subject(:check) { described_class.new(check_force_https: false).force_https_check }
it "returns nil" do it "returns nil" do
SiteSetting.force_https = true SiteSetting.force_https = true
expect(subject).to be_nil expect(check).to be_nil
SiteSetting.force_https = false SiteSetting.force_https = false
expect(subject).to be_nil expect(check).to be_nil
end end
end end

View File

@ -556,13 +556,13 @@ RSpec.describe Category do
end end
describe "new" do describe "new" do
subject { Fabricate.build(:category, user: Fabricate(:user)) } subject(:category) { Fabricate.build(:category, user: Fabricate(:user)) }
it "triggers a extensibility event" do it "triggers a extensibility event" do
event = DiscourseEvent.track_events { subject.save! }.last event = DiscourseEvent.track_events { category.save! }.last
expect(event[:event_name]).to eq(:category_created) expect(event[:event_name]).to eq(:category_created)
expect(event[:params].first).to eq(subject) expect(event[:params].first).to eq(category)
end end
end end

View File

@ -502,13 +502,13 @@ RSpec.describe Group do
end end
describe "new" do describe "new" do
subject { Fabricate.build(:group) } subject(:group) { Fabricate.build(:group) }
it "triggers a extensibility event" do it "triggers a extensibility event" do
event = DiscourseEvent.track_events { subject.save! }.first event = DiscourseEvent.track_events { group.save! }.first
expect(event[:event_name]).to eq(:group_created) expect(event[:event_name]).to eq(:group_created)
expect(event[:params].first).to eq(subject) expect(event[:params].first).to eq(group)
end end
end end

View File

@ -24,12 +24,13 @@ RSpec.describe Permalink do
end end
describe "target_url" do describe "target_url" do
subject(:target_url) { permalink.target_url }
let(:permalink) { Fabricate.build(:permalink) } let(:permalink) { Fabricate.build(:permalink) }
let(:topic) { Fabricate(:topic) } let(:topic) { Fabricate(:topic) }
let(:post) { Fabricate(:post, topic: topic) } let(:post) { Fabricate(:post, topic: topic) }
let(:category) { Fabricate(:category) } let(:category) { Fabricate(:category) }
let(:tag) { Fabricate(:tag) } let(:tag) { Fabricate(:tag) }
subject(:target_url) { permalink.target_url }
it "returns a topic url when topic_id is set" do it "returns a topic url when topic_id is set" do
permalink.topic_id = topic.id permalink.topic_id = topic.id

View File

@ -46,6 +46,8 @@ RSpec.describe Report do
describe "counting" do describe "counting" do
describe "requests" do describe "requests" do
subject(:json) { Report.find("http_total_reqs").as_json }
before do before do
freeze_time DateTime.parse("2017-03-01 12:00") freeze_time DateTime.parse("2017-03-01 12:00")
@ -89,8 +91,6 @@ RSpec.describe Report do
ApplicationRequest.insert_all(application_requests) ApplicationRequest.insert_all(application_requests)
end end
subject(:json) { Report.find("http_total_reqs").as_json }
it "counts the correct records" do it "counts the correct records" do
expect(json[:data].size).to eq(31) # today and 30 full days expect(json[:data].size).to eq(31) # today and 30 full days
expect(json[:data][0..-2].sum { |d| d[:y] }).to eq(300) expect(json[:data][0..-2].sum { |d| d[:y] }).to eq(300)

View File

@ -52,7 +52,7 @@ RSpec.describe ScreenedEmail do
end end
describe "#should_block?" do describe "#should_block?" do
subject { ScreenedEmail.should_block?(email) } subject(:should_block) { ScreenedEmail.should_block?(email) }
it "automatically blocks via email canonicalization" do it "automatically blocks via email canonicalization" do
SiteSetting.levenshtein_distance_spammer_emails = 0 SiteSetting.levenshtein_distance_spammer_emails = 0
@ -63,7 +63,7 @@ RSpec.describe ScreenedEmail do
end end
it "returns false if a record with the email doesn't exist" do it "returns false if a record with the email doesn't exist" do
expect(subject).to eq(false) expect(should_block).to eq(false)
end end
it "returns true when there is a record with the email" do it "returns true when there is a record with the email" do
@ -86,7 +86,7 @@ RSpec.describe ScreenedEmail do
shared_examples "when a ScreenedEmail record matches" do shared_examples "when a ScreenedEmail record matches" do
it "updates statistics" do it "updates statistics" do
freeze_time do freeze_time do
expect { subject }.to change { screened_email.reload.match_count }.by(1) expect { should_block }.to change { screened_email.reload.match_count }.by(1)
expect(screened_email.last_match_at).to eq_time(Time.zone.now) expect(screened_email.last_match_at).to eq_time(Time.zone.now)
end end
end end

View File

@ -25,27 +25,28 @@ RSpec.describe ScreenedUrl do
end end
describe "normalize" do describe "normalize" do
let(:record) { described_class.new(@params) } subject(:normalized) do
subject do
record.normalize record.normalize
record record
end end
let(:record) { described_class.new(@params) }
%w[http:// HTTP:// https:// HTTPS://].each do |prefix| %w[http:// HTTP:// https:// HTTPS://].each do |prefix|
it "strips #{prefix}" do it "strips #{prefix}" do
@params = valid_params.merge(url: url.gsub("http://", prefix)) @params = valid_params.merge(url: url.gsub("http://", prefix))
expect(subject.url).to eq(url.gsub("http://", "")) expect(normalized.url).to eq(url.gsub("http://", ""))
end end
end end
it "strips trailing slash" do it "strips trailing slash" do
@params = valid_params.merge(url: "silverbullet.in/") @params = valid_params.merge(url: "silverbullet.in/")
expect(subject.url).to eq("silverbullet.in") expect(normalized.url).to eq("silverbullet.in")
end end
it "strips trailing slashes" do it "strips trailing slashes" do
@params = valid_params.merge(url: "silverbullet.in/buy///") @params = valid_params.merge(url: "silverbullet.in/buy///")
expect(subject.url).to eq("silverbullet.in/buy") expect(normalized.url).to eq("silverbullet.in/buy")
end end
it "downcases domains" do it "downcases domains" do

View File

@ -35,13 +35,13 @@ RSpec.describe Tag do
end end
describe "new" do describe "new" do
subject { Fabricate.build(:tag) } subject(:tag) { Fabricate.build(:tag) }
it "triggers a extensibility event" do it "triggers a extensibility event" do
event = DiscourseEvent.track_events { subject.save! }.last event = DiscourseEvent.track_events { tag.save! }.last
expect(event[:event_name]).to eq(:tag_created) expect(event[:event_name]).to eq(:tag_created)
expect(event[:params].first).to eq(subject) expect(event[:params].first).to eq(tag)
end end
it "prevents case-insensitive duplicates" do it "prevents case-insensitive duplicates" do
@ -59,13 +59,13 @@ RSpec.describe Tag do
end end
describe "destroy" do describe "destroy" do
subject { Fabricate(:tag) } subject(:tag) { Fabricate(:tag) }
it "triggers a extensibility event" do it "triggers a extensibility event" do
event = DiscourseEvent.track_events { subject.destroy! }.last event = DiscourseEvent.track_events { tag.destroy! }.last
expect(event[:event_name]).to eq(:tag_destroyed) expect(event[:event_name]).to eq(:tag_destroyed)
expect(event[:params].first).to eq(subject) expect(event[:params].first).to eq(tag)
end end
it "removes it from its tag group" do it "removes it from its tag group" do

View File

@ -1,10 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe TrustLevel3Requirements do RSpec.describe TrustLevel3Requirements do
fab!(:user) { Fabricate(:user) }
subject(:tl3_requirements) { described_class.new(user) } subject(:tl3_requirements) { described_class.new(user) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:topic1) { Fabricate(:topic) } fab!(:topic1) { Fabricate(:topic) }
fab!(:topic2) { Fabricate(:topic) } fab!(:topic2) { Fabricate(:topic) }
fab!(:topic3) { Fabricate(:topic) } fab!(:topic3) { Fabricate(:topic) }

View File

@ -2,12 +2,14 @@
RSpec.describe UserField do RSpec.describe UserField do
describe "doesn't validate presence of name if field type is 'confirm'" do describe "doesn't validate presence of name if field type is 'confirm'" do
subject { described_class.new(field_type: "confirm") } subject(:confirm_field) { described_class.new(field_type: "confirm") }
it { is_expected.not_to validate_presence_of :name } it { is_expected.not_to validate_presence_of :name }
end end
describe "validates presence of name for other field types" do describe "validates presence of name for other field types" do
subject { described_class.new(field_type: "dropdown") } subject(:dropdown_field) { described_class.new(field_type: "dropdown") }
it { is_expected.to validate_presence_of :name } it { is_expected.to validate_presence_of :name }
end end

View File

@ -641,35 +641,33 @@ RSpec.describe User do
end end
describe "new" do describe "new" do
subject { Fabricate.build(:user) } subject(:user) { Fabricate.build(:user) }
it { is_expected.to be_valid } it { is_expected.to be_valid }
it { is_expected.not_to be_admin } it { is_expected.not_to be_admin }
it { is_expected.not_to be_approved } it { is_expected.not_to be_approved }
it "is properly initialized" do it "is properly initialized" do
expect(subject.approved_at).to be_blank expect(user.approved_at).to be_blank
expect(subject.approved_by_id).to be_blank expect(user.approved_by_id).to be_blank
end end
it "triggers an extensibility event" do it "triggers an extensibility event" do
event = DiscourseEvent.track_events { subject.save! }.first event = DiscourseEvent.track_events { user.save! }.first
expect(event[:event_name]).to eq(:user_created) expect(event[:event_name]).to eq(:user_created)
expect(event[:params].first).to eq(subject) expect(event[:params].first).to eq(user)
end end
context "with after_save" do context "with after_save" do
before { subject.save! } before { user.save! }
it "has correct settings" do it "has correct settings" do
expect(subject.email_tokens).to be_present expect(user.email_tokens).to be_present
expect(subject.user_stat).to be_present expect(user.user_stat).to be_present
expect(subject.user_profile).to be_present expect(user.user_profile).to be_present
expect(subject.user_option.email_messages_level).to eq( expect(user.user_option.email_messages_level).to eq(UserOption.email_level_types[:always])
UserOption.email_level_types[:always], expect(user.user_option.email_level).to eq(UserOption.email_level_types[:only_when_away])
)
expect(subject.user_option.email_level).to eq(UserOption.email_level_types[:only_when_away])
end end
end end
@ -756,41 +754,37 @@ RSpec.describe User do
end end
describe "staff and regular users" do describe "staff and regular users" do
let(:user) { Fabricate.build(:user) } subject(:user) { Fabricate.build(:user) }
describe "#staff?" do describe "#staff?" do
subject { user.staff? } it { is_expected.not_to be_staff }
it { is_expected.to eq(false) }
context "for a moderator user" do context "for a moderator user" do
before { user.moderator = true } before { user.moderator = true }
it { is_expected.to eq(true) } it { is_expected.to be_staff }
end end
context "for an admin user" do context "for an admin user" do
before { user.admin = true } before { user.admin = true }
it { is_expected.to eq(true) } it { is_expected.to be_staff }
end end
end end
describe "#regular?" do describe "#regular?" do
subject { user.regular? } it { is_expected.to be_regular }
it { is_expected.to eq(true) }
context "for a moderator user" do context "for a moderator user" do
before { user.moderator = true } before { user.moderator = true }
it { is_expected.to eq(false) } it { is_expected.not_to be_regular }
end end
context "for an admin user" do context "for an admin user" do
before { user.admin = true } before { user.admin = true }
it { is_expected.to eq(false) } it { is_expected.not_to be_regular }
end end
end end
end end
@ -3251,7 +3245,7 @@ RSpec.describe User do
end end
it "returns false if no whispers groups exist" do it "returns false if no whispers groups exist" do
expect(subject.whisperer?).to eq(false) expect(user.whisperer?).to eq(false)
end end
end end

Some files were not shown because too many files have changed in this diff Show More