377 lines
14 KiB
Ruby
377 lines
14 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "rails_helper"
|
|
|
|
describe Chat::ChatChannelArchiveService do
|
|
class FakeArchiveError < StandardError
|
|
end
|
|
|
|
fab!(:channel) { Fabricate(:category_channel) }
|
|
fab!(:user) { Fabricate(:user, admin: true) }
|
|
fab!(:category) { Fabricate(:category) }
|
|
let(:topic_params) { { topic_title: "This will be a new topic", category_id: category.id } }
|
|
subject { Chat::ChatChannelArchiveService }
|
|
|
|
before { SiteSetting.chat_enabled = true }
|
|
|
|
describe "#create_archive_process" do
|
|
before { 3.times { Fabricate(:chat_message, chat_channel: channel) } }
|
|
|
|
it "marks the channel as read_only" do
|
|
subject.create_archive_process(
|
|
chat_channel: channel,
|
|
acting_user: user,
|
|
topic_params: topic_params,
|
|
)
|
|
expect(channel.reload.status).to eq("read_only")
|
|
end
|
|
|
|
it "creates the chat channel archive record to save progress and topic params" do
|
|
subject.create_archive_process(
|
|
chat_channel: channel,
|
|
acting_user: user,
|
|
topic_params: topic_params,
|
|
)
|
|
channel_archive = ChatChannelArchive.find_by(chat_channel: channel)
|
|
expect(channel_archive.archived_by).to eq(user)
|
|
expect(channel_archive.destination_topic_title).to eq("This will be a new topic")
|
|
expect(channel_archive.destination_category_id).to eq(category.id)
|
|
expect(channel_archive.total_messages).to eq(3)
|
|
expect(channel_archive.archived_messages).to eq(0)
|
|
end
|
|
|
|
it "enqueues the archive job" do
|
|
channel_archive =
|
|
subject.create_archive_process(
|
|
chat_channel: channel,
|
|
acting_user: user,
|
|
topic_params: topic_params,
|
|
)
|
|
expect(
|
|
job_enqueued?(
|
|
job: :chat_channel_archive,
|
|
args: {
|
|
chat_channel_archive_id: channel_archive.id,
|
|
},
|
|
),
|
|
).to eq(true)
|
|
end
|
|
|
|
it "does nothing if there is already an archive record for the channel" do
|
|
subject.create_archive_process(
|
|
chat_channel: channel,
|
|
acting_user: user,
|
|
topic_params: topic_params,
|
|
)
|
|
expect {
|
|
subject.create_archive_process(
|
|
chat_channel: channel,
|
|
acting_user: user,
|
|
topic_params: topic_params,
|
|
)
|
|
}.not_to change { ChatChannelArchive.count }
|
|
end
|
|
|
|
it "does not count already deleted messages toward the archive total" do
|
|
new_message = Fabricate(:chat_message, chat_channel: channel)
|
|
new_message.trash!
|
|
channel_archive =
|
|
subject.create_archive_process(
|
|
chat_channel: channel,
|
|
acting_user: user,
|
|
topic_params: topic_params,
|
|
)
|
|
expect(channel_archive.total_messages).to eq(3)
|
|
end
|
|
end
|
|
|
|
describe "#execute" do
|
|
def create_messages(num)
|
|
num.times { Fabricate(:chat_message, chat_channel: channel) }
|
|
end
|
|
|
|
def start_archive
|
|
@channel_archive =
|
|
subject.create_archive_process(
|
|
chat_channel: channel,
|
|
acting_user: user,
|
|
topic_params: topic_params,
|
|
)
|
|
end
|
|
|
|
context "when archiving to a new topic" do
|
|
let(:topic_params) do
|
|
{ topic_title: "This will be a new topic", category_id: category.id, tags: %w[news gossip] }
|
|
end
|
|
|
|
it "makes a topic, deletes all the messages, creates posts for batches of messages, and changes the channel to archived" do
|
|
create_messages(50) && start_archive
|
|
reaction_message = ChatMessage.last
|
|
ChatMessageReaction.create!(
|
|
chat_message: reaction_message,
|
|
user: Fabricate(:user),
|
|
emoji: "+1",
|
|
)
|
|
stub_const(Chat::ChatChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do
|
|
subject.new(@channel_archive).execute
|
|
end
|
|
|
|
@channel_archive.reload
|
|
expect(@channel_archive.destination_topic.title).to eq("This will be a new topic")
|
|
expect(@channel_archive.destination_topic.category).to eq(category)
|
|
expect(@channel_archive.destination_topic.user).to eq(Discourse.system_user)
|
|
expect(@channel_archive.destination_topic.tags.map(&:name)).to match_array(%w[news gossip])
|
|
|
|
topic = @channel_archive.destination_topic
|
|
expect(topic.posts.count).to eq(11)
|
|
topic
|
|
.posts
|
|
.where.not(post_number: 1)
|
|
.each do |post|
|
|
expect(post.raw).to include("[chat")
|
|
expect(post.raw).to include("noLink=\"true\"")
|
|
expect(post.user).to eq(Discourse.system_user)
|
|
|
|
if post.raw.include?(";#{reaction_message.id};")
|
|
expect(post.raw).to include("reactions=")
|
|
end
|
|
end
|
|
expect(topic.archived).to eq(true)
|
|
|
|
expect(@channel_archive.archived_messages).to eq(50)
|
|
expect(@channel_archive.chat_channel.status).to eq("archived")
|
|
expect(@channel_archive.chat_channel.chat_messages.count).to eq(0)
|
|
end
|
|
|
|
it "does not stop the process if the post length is too high (validations disabled)" do
|
|
create_messages(50) && start_archive
|
|
SiteSetting.max_post_length = 1
|
|
subject.new(@channel_archive).execute
|
|
expect(@channel_archive.reload.complete?).to eq(true)
|
|
end
|
|
|
|
it "successfully links uploads from messages to the post" do
|
|
create_messages(3) && start_archive
|
|
UploadReference.create(target: ChatMessage.last, upload: Fabricate(:upload))
|
|
subject.new(@channel_archive).execute
|
|
expect(@channel_archive.reload.complete?).to eq(true)
|
|
expect(@channel_archive.destination_topic.posts.last.upload_references.count).to eq(1)
|
|
end
|
|
|
|
it "successfully sends a private message to the archiving user" do
|
|
create_messages(3) && start_archive
|
|
subject.new(@channel_archive).execute
|
|
expect(@channel_archive.reload.complete?).to eq(true)
|
|
pm_topic = Topic.private_messages.last
|
|
expect(pm_topic.topic_allowed_users.first.user).to eq(@channel_archive.archived_by)
|
|
expect(pm_topic.title).to eq(
|
|
I18n.t("system_messages.chat_channel_archive_complete.subject_template"),
|
|
)
|
|
end
|
|
|
|
it "does not continue archiving if the destination topic fails to be created" do
|
|
SiteSetting.max_emojis_in_title = 1
|
|
|
|
create_messages(3) && start_archive
|
|
@channel_archive.update!(destination_topic_title: "Wow this is the new title :tada: :joy:")
|
|
subject.new(@channel_archive).execute
|
|
expect(@channel_archive.reload.complete?).to eq(false)
|
|
expect(@channel_archive.reload.failed?).to eq(true)
|
|
expect(@channel_archive.archive_error).to eq("Title can't have more than 1 emoji")
|
|
|
|
pm_topic = Topic.private_messages.last
|
|
expect(pm_topic.title).to eq(
|
|
I18n.t("system_messages.chat_channel_archive_failed.subject_template"),
|
|
)
|
|
expect(pm_topic.first_post.raw).to include("Title can't have more than 1 emoji")
|
|
end
|
|
|
|
context "when enable_experimental_hashtag_autocomplete" do
|
|
before { SiteSetting.enable_experimental_hashtag_autocomplete = true }
|
|
|
|
it "uses the channel slug to autolink a hashtag for the channel in the PM" do
|
|
create_messages(3) && start_archive
|
|
subject.new(@channel_archive).execute
|
|
expect(@channel_archive.reload.complete?).to eq(true)
|
|
pm_topic = Topic.private_messages.last
|
|
expect(pm_topic.first_post.cooked).to include(
|
|
"<a class=\"hashtag-cooked\" href=\"#{channel.relative_url}\" data-type=\"channel\" data-slug=\"#{channel.slug}\" data-ref=\"#{channel.slug}::channel\"><svg class=\"fa d-icon d-icon-comment svg-icon svg-node\"><use href=\"#comment\"></use></svg><span>#{channel.title(user)}</span></a>",
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "channel members" do
|
|
before do
|
|
create_messages(3)
|
|
channel
|
|
.chat_messages
|
|
.map(&:user)
|
|
.each do |user|
|
|
UserChatChannelMembership.create!(chat_channel: channel, user: user, following: true)
|
|
end
|
|
end
|
|
|
|
it "unfollows (leaves) the channel for all users" do
|
|
expect(
|
|
UserChatChannelMembership.where(chat_channel: channel, following: true).count,
|
|
).to eq(3)
|
|
start_archive
|
|
subject.new(@channel_archive).execute
|
|
expect(@channel_archive.reload.complete?).to eq(true)
|
|
expect(
|
|
UserChatChannelMembership.where(chat_channel: channel, following: true).count,
|
|
).to eq(0)
|
|
end
|
|
|
|
it "resets unread state for all users" do
|
|
UserChatChannelMembership.last.update!(
|
|
last_read_message_id: channel.chat_messages.first.id,
|
|
)
|
|
start_archive
|
|
subject.new(@channel_archive).execute
|
|
expect(@channel_archive.reload.complete?).to eq(true)
|
|
expect(UserChatChannelMembership.last.last_read_message_id).to eq(
|
|
channel.chat_messages.last.id,
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "chat_archive_destination_topic_status setting" do
|
|
context "when set to archived" do
|
|
before { SiteSetting.chat_archive_destination_topic_status = "archived" }
|
|
|
|
it "archives the topic" do
|
|
create_messages(3) && start_archive
|
|
subject.new(@channel_archive).execute
|
|
topic = @channel_archive.destination_topic
|
|
topic.reload
|
|
expect(topic.archived).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when set to open" do
|
|
before { SiteSetting.chat_archive_destination_topic_status = "open" }
|
|
|
|
it "leaves the topic open" do
|
|
create_messages(3) && start_archive
|
|
subject.new(@channel_archive).execute
|
|
topic = @channel_archive.destination_topic
|
|
topic.reload
|
|
expect(topic.archived).to eq(false)
|
|
expect(topic.open?).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when set to closed" do
|
|
before { SiteSetting.chat_archive_destination_topic_status = "closed" }
|
|
|
|
it "closes the topic" do
|
|
create_messages(3) && start_archive
|
|
subject.new(@channel_archive).execute
|
|
topic = @channel_archive.destination_topic
|
|
topic.reload
|
|
expect(topic.archived).to eq(false)
|
|
expect(topic.closed?).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when archiving to an existing topic" do
|
|
it "does not change the status of the topic" do
|
|
create_messages(3) && start_archive
|
|
@channel_archive.update(
|
|
destination_topic_title: nil,
|
|
destination_topic_id: Fabricate(:topic).id,
|
|
)
|
|
subject.new(@channel_archive).execute
|
|
topic = @channel_archive.destination_topic
|
|
topic.reload
|
|
expect(topic.archived).to eq(false)
|
|
expect(topic.closed?).to eq(false)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when archiving to an existing topic" do
|
|
fab!(:topic) { Fabricate(:topic) }
|
|
let(:topic_params) { { topic_id: topic.id } }
|
|
|
|
before { 3.times { Fabricate(:post, topic: topic) } }
|
|
|
|
it "deletes all the messages, creates posts for batches of messages, and changes the channel to archived" do
|
|
create_messages(50) && start_archive
|
|
reaction_message = ChatMessage.last
|
|
ChatMessageReaction.create!(
|
|
chat_message: reaction_message,
|
|
user: Fabricate(:user),
|
|
emoji: "+1",
|
|
)
|
|
stub_const(Chat::ChatChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do
|
|
subject.new(@channel_archive).execute
|
|
end
|
|
|
|
@channel_archive.reload
|
|
expect(@channel_archive.destination_topic.title).to eq(topic.title)
|
|
expect(@channel_archive.destination_topic.category).to eq(topic.category)
|
|
expect(@channel_archive.destination_topic.user).to eq(topic.user)
|
|
|
|
topic = @channel_archive.destination_topic
|
|
|
|
# existing posts + 10 archive posts
|
|
expect(topic.posts.count).to eq(13)
|
|
topic
|
|
.posts
|
|
.where.not(post_number: [1, 2, 3])
|
|
.each do |post|
|
|
expect(post.raw).to include("[chat")
|
|
expect(post.raw).to include("noLink=\"true\"")
|
|
expect(post.user).to eq(Discourse.system_user)
|
|
|
|
if post.raw.include?(";#{reaction_message.id};")
|
|
expect(post.raw).to include("reactions=")
|
|
end
|
|
end
|
|
expect(topic.archived).to eq(false)
|
|
|
|
expect(@channel_archive.archived_messages).to eq(50)
|
|
expect(@channel_archive.chat_channel.status).to eq("archived")
|
|
expect(@channel_archive.chat_channel.chat_messages.count).to eq(0)
|
|
end
|
|
|
|
it "handles errors gracefully, sends a private message to the archiving user, and is idempotent on retry" do
|
|
Rails.logger = @fake_logger = FakeLogger.new
|
|
create_messages(35) && start_archive
|
|
|
|
Chat::ChatChannelArchiveService
|
|
.any_instance
|
|
.stubs(:create_post)
|
|
.raises(FakeArchiveError.new("this is a test error"))
|
|
|
|
stub_const(Chat::ChatChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do
|
|
expect { subject.new(@channel_archive).execute }.to raise_error(FakeArchiveError)
|
|
end
|
|
|
|
expect(@channel_archive.reload.archive_error).to eq("this is a test error")
|
|
|
|
pm_topic = Topic.private_messages.last
|
|
expect(pm_topic.topic_allowed_users.first.user).to eq(@channel_archive.archived_by)
|
|
expect(pm_topic.title).to eq(
|
|
I18n.t("system_messages.chat_channel_archive_failed.subject_template"),
|
|
)
|
|
|
|
Chat::ChatChannelArchiveService.any_instance.unstub(:create_post)
|
|
stub_const(Chat::ChatChannelArchiveService, "ARCHIVED_MESSAGES_PER_POST", 5) do
|
|
subject.new(@channel_archive).execute
|
|
end
|
|
|
|
@channel_archive.reload
|
|
expect(@channel_archive.archive_error).to eq(nil)
|
|
expect(@channel_archive.archived_messages).to eq(35)
|
|
expect(@channel_archive.complete?).to eq(true)
|
|
# existing posts + 7 archive posts
|
|
expect(topic.posts.count).to eq(10)
|
|
end
|
|
end
|
|
end
|
|
end
|