discourse/plugins/chat/spec/integration/outgoing_web_hooks_spec.rb
David Battersby f1e22dfebd
FEATURE: add grace period for chat edits (#23800)
This change allows users to edit their chat messages based on the criteria added to Site Settings.

If the grace period conditions are met then there will be no (edited) text applied to the message.

The following site settings are added to chat:

chat editing grace period (seconds since message created)
chat editing grace period max diff for low trust levels (number of characters changed)
chat editing grace period max diff for high trust levels (number of characters changed)
2023-10-23 16:40:30 +08:00

246 lines
10 KiB
Ruby

# frozen_string_literal: true
RSpec.describe "Outgoing chat webhooks" do
before do
SiteSetting.chat_enabled = true
SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:everyone]
end
describe "chat messages" do
fab!(:web_hook) { Fabricate(:outgoing_chat_message_web_hook) }
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
let(:message_content) { "This is a test message" }
let(:new_message_content) { "This is the edited message" }
let(:job_args) do
Jobs::EmitWebHookEvent
.jobs
.map { |job| job["args"].first }
.find { |args| args["event_type"] == "chat_message" }
end
let(:event_name) { job_args["event_name"] }
let(:event_category_id) { job_args["category_id"] }
let(:payload) { JSON.parse(job_args["payload"]) }
def expect_response_to_be_successful
expect(response.status).to eq(200)
end
def expect_web_hook_event_name_to_be(name)
expect(event_name).to eq(name)
end
def expect_web_hook_event_category_to_be(category)
expect(event_category_id).to eq(category.id)
end
def expect_web_hook_payload_message_to_match(message:, user:, &block)
payload_message = payload["message"]
expect(payload_message["id"]).to eq(message.id)
expect(payload_message["message"]).to eq(message.message)
expect(payload_message["cooked"]).to eq(message.cooked)
expect(payload_message["created_at"]).to eq(message.created_at.iso8601)
expect(payload_message["excerpt"]).to eq(message.excerpt)
expect(payload_message["chat_channel_id"]).to eq(message.chat_channel_id)
expect(payload_message["mentioned_users"]).to be_empty
expect(payload_message["available_flags"]).to be_empty
expect(payload_message["user"]["id"]).to eq(user.id)
expect(payload_message["user"]["username"]).to eq(user.username)
expect(payload_message["user"]["avatar_template"]).to eq(user.avatar_template)
expect(payload_message["user"]["admin"]).to eq(user.admin?)
expect(payload_message["user"]["staff"]).to eq(user.staff?)
expect(payload_message["user"]["moderator"]).to eq(user.moderator?)
expect(payload_message["user"]["new_user"]).to eq(user.trust_level == TrustLevel[0])
expect(payload_message["user"]["primary_group_name"]).to eq(user.primary_group&.name)
expect(payload_message["uploads"]).to be_empty
yield(payload_message) if block_given?
end
def expect_web_hook_payload_channel_to_match_category(channel:, category:, &block)
payload_channel = payload["channel"]
expect(payload_channel["id"]).to eq(channel.id)
expect(payload_channel["allow_channel_wide_mentions"]).to eq(
channel.allow_channel_wide_mentions,
)
expect(payload_channel["chatable_id"]).to eq(category.id)
expect(payload_channel["chatable_type"]).to eq("Category")
expect(payload_channel["chatable_url"]).to eq(category.url)
expect(payload_channel["title"]).to eq(channel.title)
expect(payload_channel["slug"]).to eq(channel.slug)
yield(payload_channel) if block_given?
end
def expect_web_hook_payload_channel_to_match_direct_message(channel:, direct_message:, &block)
payload_channel = payload["channel"]
expect(payload_channel["id"]).to eq(channel.id)
expect(payload_channel["allow_channel_wide_mentions"]).to eq(
channel.allow_channel_wide_mentions,
)
expect(payload_channel["chatable_id"]).to eq(direct_message.id)
expect(payload_channel["chatable_type"]).to eq("DirectMessage")
expect(payload_channel["chatable_url"]).to be_nil
expect(payload_channel["chatable"]["users"][0]["id"]).to eq(user2.id)
expect(payload_channel["chatable"]["users"][0]["username"]).to eq(user2.username)
expect(payload_channel["chatable"]["users"][0]["name"]).to eq(user2.name)
expect(payload_channel["chatable"]["users"][0]["avatar_template"]).to eq(
user2.avatar_template,
)
expect(payload_channel["chatable"]["users"][0]["can_chat"]).to eq(true)
expect(payload_channel["chatable"]["users"][0]["has_chat_enabled"]).to eq(true)
expect(payload_channel["title"]).to eq(channel.title(user1))
expect(payload_channel["slug"]).to be_nil
yield(payload_channel) if block_given?
end
context "for a category channel" do
fab!(:category) { Fabricate(:category) }
fab!(:chat_channel) { Fabricate(:category_channel, chatable: category) }
fab!(:chat_message) { Fabricate(:chat_message, chat_channel: chat_channel, user: user1) }
before do
[user1, user2].each do |user|
Chat::UserChatChannelMembership.create(
user: user,
chat_channel: chat_channel,
following: true,
)
end
sign_in(user1)
end
it "triggers a webhook when a chat message is created" do
post "/chat/#{chat_channel.id}.json", params: { message: message_content }
expect_response_to_be_successful
expect_web_hook_event_name_to_be("chat_message_created")
expect_web_hook_event_category_to_be(category)
expect_web_hook_payload_message_to_match(
message: Chat::Message.last,
user: user1,
) { |payload_message| expect(payload_message["message"]).to eq(message_content) }
expect_web_hook_payload_channel_to_match_category(channel: chat_channel, category: category)
end
it "triggers a webhook when a chat message is edited" do
put "/chat/api/channels/#{chat_channel.id}/messages/#{chat_message.id}.json",
params: {
message: new_message_content,
}
expect_response_to_be_successful
expect_web_hook_event_name_to_be("chat_message_edited")
expect_web_hook_event_category_to_be(category)
expect_web_hook_payload_message_to_match(
message: Chat::Message.last,
user: user1,
) { |payload_message| expect(payload_message["message"]).to eq(new_message_content) }
expect_web_hook_payload_channel_to_match_category(channel: chat_channel, category: category)
end
it "triggers a webhook when a chat message is trashed" do
delete "/chat/api/channels/#{chat_message.chat_channel_id}/messages/#{chat_message.id}.json"
expect_response_to_be_successful
expect(chat_message.reload.trashed?).to eq(true)
expect_web_hook_event_name_to_be("chat_message_trashed")
expect_web_hook_event_category_to_be(category)
expect_web_hook_payload_message_to_match(message: chat_message, user: user1)
expect_web_hook_payload_channel_to_match_category(channel: chat_channel, category: category)
end
it "triggers a webhook when a trashed chat message is restored" do
chat_message.trash!(user1)
expect(chat_message.reload.trashed?).to eq(true)
put "/chat/api/channels/#{chat_channel.id}/messages/#{chat_message.id}/restore.json"
expect_response_to_be_successful
expect(chat_message.reload.trashed?).to eq(false)
expect_web_hook_event_name_to_be("chat_message_restored")
expect_web_hook_event_category_to_be(category)
expect_web_hook_payload_message_to_match(message: chat_message, user: user1)
expect_web_hook_payload_channel_to_match_category(channel: chat_channel, category: category)
end
end
context "for a direct message channel" do
fab!(:direct_message) { Fabricate(:direct_message, users: [user1, user2]) }
fab!(:direct_message_channel) { Fabricate(:direct_message_channel, chatable: direct_message) }
fab!(:chat_message) do
Fabricate(:chat_message, chat_channel: direct_message_channel, user: user1)
end
before { sign_in(user1) }
it "triggers a webhook when a chat message is created" do
post "/chat/#{direct_message_channel.id}.json", params: { message: message_content }
expect_response_to_be_successful
expect_web_hook_event_name_to_be("chat_message_created")
expect_web_hook_payload_message_to_match(
message: Chat::Message.last,
user: user1,
) { |payload_message| expect(payload_message["message"]).to eq(message_content) }
expect_web_hook_payload_channel_to_match_direct_message(
channel: direct_message_channel,
direct_message: direct_message,
)
end
it "triggers a webhook when a chat message is edited" do
put "/chat/api/channels/#{direct_message_channel.id}/messages/#{chat_message.id}.json",
params: {
message: new_message_content,
}
expect_response_to_be_successful
expect_web_hook_event_name_to_be("chat_message_edited")
expect_web_hook_payload_message_to_match(
message: Chat::Message.last,
user: user1,
) { |payload_message| expect(payload_message["message"]).to eq(new_message_content) }
expect_web_hook_payload_channel_to_match_direct_message(
channel: direct_message_channel,
direct_message: direct_message,
)
end
it "triggers a webhook when a chat message is trashed" do
delete "/chat/api/channels/#{chat_message.chat_channel_id}/messages/#{chat_message.id}.json"
expect_response_to_be_successful
expect(chat_message.reload.trashed?).to eq(true)
expect_web_hook_event_name_to_be("chat_message_trashed")
expect_web_hook_payload_message_to_match(message: chat_message, user: user1)
expect_web_hook_payload_channel_to_match_direct_message(
channel: direct_message_channel,
direct_message: direct_message,
)
end
it "triggers a webhook when a trashed chat message is restored" do
chat_message.trash!(user1)
expect(chat_message.reload.trashed?).to eq(true)
put "/chat/api/channels/#{direct_message_channel.id}/messages/#{chat_message.id}/restore.json"
expect_response_to_be_successful
expect(chat_message.reload.trashed?).to eq(false)
expect_web_hook_event_name_to_be("chat_message_restored")
expect_web_hook_payload_message_to_match(message: chat_message, user: user1)
expect_web_hook_payload_channel_to_match_direct_message(
channel: direct_message_channel,
direct_message: direct_message,
)
end
end
end
end