discourse/plugins/chat/spec/requests/chat_controller_spec.rb
Jarek Radosz 8edf414929
DEV: Drop obsolete chat controller specs (#39525)
…and re-add the only one that wasn't covered
2026-04-24 15:12:40 +02:00

365 lines
12 KiB
Ruby

# frozen_string_literal: true
RSpec.describe Chat::ChatController do
fab!(:user)
fab!(:other_user, :user)
fab!(:admin)
fab!(:category)
fab!(:chat_channel) { Fabricate(:category_channel, chatable: category) }
fab!(:dm_chat_channel) { Fabricate(:direct_message_channel, users: [user, other_user, admin]) }
fab!(:tag)
MESSAGE_COUNT = 70
MESSAGE_COUNT.times do |n|
fab!("message_#{n}") do
Fabricate(
:chat_message,
chat_channel: chat_channel,
user: other_user,
message: "message #{n}",
)
end
end
before do
SiteSetting.chat_enabled = true
SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:everyone]
end
def flag_message(message, flagger, flag_type: ReviewableScore.types[:off_topic])
Chat::ReviewQueue.new.flag_message(message, Guardian.new(flagger), flag_type)[:reviewable]
end
describe "#rebake" do
fab!(:chat_message) { Fabricate(:chat_message, chat_channel: chat_channel, user: user) }
it "works" do
sign_in(admin)
put "/chat/#{chat_channel.id}/#{chat_message.id}/rebake.json"
expect(response.status).to eq(200)
end
context "when message does not exist" do
it "returns a 404" do
sign_in(admin)
put "/chat/#{chat_channel.id}/-999/rebake.json"
expect(response.status).to eq(404)
end
end
context "when channel does not exist" do
it "returns a 404" do
sign_in(admin)
put "/chat/-999/#{chat_message.id}/rebake.json"
expect(response.status).to eq(404)
end
end
context "when user cannot access the channel" do
fab!(:inaccessible_channel, :private_category_channel)
it "returns a 403" do
sign_in(Fabricate(:user))
put "/chat/#{inaccessible_channel.id}/-999/rebake.json"
expect(response.status).to eq(403)
end
end
context "when user cannot rebake" do
it "returns a 403" do
sign_in(Fabricate(:user))
put "/chat/#{chat_channel.id}/#{chat_message.id}/rebake.json"
expect(response.status).to eq(403)
end
end
end
describe "react" do
fab!(:chat_channel, :category_channel)
fab!(:chat_message) { Fabricate(:chat_message, chat_channel: chat_channel, user: user) }
fab!(:user_membership) do
Fabricate(:user_chat_channel_membership, chat_channel: chat_channel, user: user)
end
fab!(:private_chat_channel) do
Fabricate(:category_channel, chatable: Fabricate(:private_category, group: Fabricate(:group)))
end
fab!(:private_chat_message) do
Fabricate(:chat_message, chat_channel: private_chat_channel, user: admin)
end
fab!(:private_user_membership) do
Fabricate(:user_chat_channel_membership, chat_channel: private_chat_channel, user: user)
end
fab!(:chat_channel_no_memberships, :category_channel)
fab!(:chat_message_no_memberships) do
Fabricate(:chat_message, chat_channel: chat_channel_no_memberships, user: user)
end
it "errors with invalid emoji" do
sign_in(user)
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: 12,
react_action: "add",
}
expect(response.status).to eq(400)
end
it "errors with invalid action" do
sign_in(user)
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: ":heart:",
react_action: "sdf",
}
expect(response.status).to eq(400)
end
it "errors when reacting to channel without a membership record" do
sign_in(user)
expect {
put "/chat/#{chat_channel_no_memberships.id}/react/#{chat_message_no_memberships.id}.json",
params: {
emoji: ":heart:",
react_action: "add",
}
}.not_to change { Chat::UserChatChannelMembership.count }
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(I18n.t("chat.errors.user_not_in_channel"))
end
it "errors when user tries to react to private channel they can't access" do
sign_in(user)
put "/chat/#{private_chat_channel.id}/react/#{private_chat_message.id}.json",
params: {
emoji: ":heart:",
react_action: "add",
}
expect(response.status).to eq(403)
end
it "errors when the user tries to react to a read_only channel" do
chat_channel.update(status: :read_only)
sign_in(user)
emoji = ":heart:"
expect {
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: emoji,
react_action: "add",
}
}.not_to change { chat_message.reactions.where(user: user, emoji: emoji).count }
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(
I18n.t("chat.errors.channel_modify_message_disallowed.#{chat_channel.status}"),
)
end
it "errors when user is silenced" do
UserSilencer.new(user).silence
sign_in(user)
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: ":heart:",
react_action: "add",
}
expect(response.status).to eq(403)
end
it "errors when max unique reactions limit is reached" do
Emoji
.all
.map(&:name)
.take(29)
.each { |emoji| chat_message.reactions.create(user: user, emoji: emoji) }
sign_in(user)
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: ":wink:",
react_action: "add",
}
expect(response.status).to eq(200)
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: ":waving_hand:",
react_action: "add",
}
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(
I18n.t("chat.errors.max_reactions_limit_reached"),
)
end
it "does not error on new duplicate reactions" do
another_user = Fabricate(:user)
Emoji
.all
.map(&:name)
.take(29)
.each { |emoji| chat_message.reactions.create(user: another_user, emoji: emoji) }
emoji = ":wink:"
chat_message.reactions.create(user: another_user, emoji: emoji)
sign_in(user)
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: emoji,
react_action: "add",
}
expect(response.status).to eq(200)
end
it "adds a reaction record correctly" do
sign_in(user)
emoji = ":heart:"
expect {
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: emoji,
react_action: "add",
}
}.to change { chat_message.reactions.where(user: user, emoji: emoji).count }.by(1)
expect(response.status).to eq(200)
end
it "removes a reaction record correctly" do
sign_in(user)
emoji = ":heart:"
chat_message.reactions.create(user: user, emoji: emoji)
expect {
put "/chat/#{chat_channel.id}/react/#{chat_message.id}.json",
params: {
emoji: emoji,
react_action: "remove",
}
}.to change { chat_message.reactions.where(user: user, emoji: emoji).count }.by(-1)
expect(response.status).to eq(200)
end
end
describe "#dismiss_retention_reminder" do
it "errors for anon" do
post "/chat/dismiss-retention-reminder.json", params: { chatable_type: "Category" }
expect(response.status).to eq(403)
end
it "errors when chatable_type isn't present" do
sign_in(user)
post "/chat/dismiss-retention-reminder.json", params: {}
expect(response.status).to eq(400)
end
it "errors when chatable_type isn't a valid option" do
sign_in(user)
post "/chat/dismiss-retention-reminder.json", params: { chatable_type: "hi" }
expect(response.status).to eq(400)
end
it "sets `dismissed_channel_retention_reminder` to true" do
sign_in(user)
expect {
post "/chat/dismiss-retention-reminder.json", params: { chatable_type: "Category" }
}.to change { user.user_option.reload.dismissed_channel_retention_reminder }.to(true)
end
it "sets `dismissed_dm_retention_reminder` to true" do
sign_in(user)
expect {
post "/chat/dismiss-retention-reminder.json", params: { chatable_type: "DirectMessage" }
}.to change { user.user_option.reload.dismissed_dm_retention_reminder }.to(true)
end
it "doesn't error if the fields are already true" do
sign_in(user)
user.user_option.update(
dismissed_channel_retention_reminder: true,
dismissed_dm_retention_reminder: true,
)
post "/chat/dismiss-retention-reminder.json", params: { chatable_type: "Category" }
expect(response.status).to eq(200)
post "/chat/dismiss-retention-reminder.json", params: { chatable_type: "DirectMessage" }
expect(response.status).to eq(200)
end
end
describe "#quote_messages" do
fab!(:channel) { Fabricate(:category_channel, chatable: category, name: "Cool Chat") }
let(:user2) { Fabricate(:user) }
let(:message1) do
Fabricate(
:chat_message,
user: user,
chat_channel: channel,
message: "an extremely insightful response :)",
)
end
let(:message2) do
Fabricate(:chat_message, user: user2, chat_channel: channel, message: "says you!")
end
let(:message3) { Fabricate(:chat_message, user: user, chat_channel: channel, message: "aw :(") }
it "returns a 403 if the user can't chat" do
SiteSetting.chat_allowed_groups = ""
sign_in(user)
post "/chat/#{channel.id}/quote.json",
params: {
message_ids: [message1.id, message2.id, message3.id],
}
expect(response.status).to eq(403)
end
it "returns a 403 if the user can't see the channel" do
category.update!(read_restricted: true)
group = Fabricate(:group)
CategoryGroup.create(
group: group,
category: category,
permission_type: CategoryGroup.permission_types[:create_post],
)
sign_in(user)
post "/chat/#{channel.id}/quote.json",
params: {
message_ids: [message1.id, message2.id, message3.id],
}
expect(response.status).to eq(403)
end
it "returns a 404 for a not found channel" do
channel.destroy
sign_in(user)
post "/chat/#{channel.id}/quote.json",
params: {
message_ids: [message1.id, message2.id, message3.id],
}
expect(response.status).to eq(404)
end
it "makes transcripts for the message ids provided" do
sign_in(user)
post "/chat/#{channel.id}/quote.json",
params: {
message_ids: [message1.id, message2.id, message3.id],
}
expect(response.status).to eq(200)
markdown = response.parsed_body["markdown"]
expect(markdown).to eq(<<~EXPECTED)
[chat quote="#{user.username};#{message1.id};#{message1.created_at.iso8601}" channel="Cool Chat" channelId="#{channel.id}" multiQuote="true" chained="true"]
an extremely insightful response :)
[/chat]
[chat quote="#{user2.username};#{message2.id};#{message2.created_at.iso8601}" chained="true"]
says you!
[/chat]
[chat quote="#{user.username};#{message3.id};#{message3.created_at.iso8601}" chained="true"]
aw :(
[/chat]
EXPECTED
end
end
end