# frozen_string_literal: true require "rails_helper" RSpec.describe Chat::IncomingChatWebhooksController do fab!(:chat_channel) { Fabricate(:category_channel) } fab!(:webhook) { Fabricate(:incoming_chat_webhook, chat_channel: chat_channel) } before { SiteSetting.chat_debug_webhook_payloads = true } describe "#create_message" do it "errors with invalid key" do post "/chat/hooks/null.json" expect(response.status).to eq(400) end it "errors when no body is present" do post "/chat/hooks/#{webhook.key}.json" expect(response.status).to eq(400) end it "errors when the body is over WEBHOOK_MAX_MESSAGE_LENGTH characters" do post "/chat/hooks/#{webhook.key}.json", params: { text: "$" * (Chat::IncomingChatWebhooksController::WEBHOOK_MAX_MESSAGE_LENGTH + 1), } expect(response.status).to eq(400) end it "creates a new chat message" do expect { post "/chat/hooks/#{webhook.key}.json", params: { text: "A new signup woo!" } }.to change { ChatMessage.where(chat_channel: chat_channel).count }.by(1) expect(response.status).to eq(200) chat_webhook_event = ChatWebhookEvent.last expect(chat_webhook_event.chat_message_id).to eq(ChatMessage.last.id) end it "handles create message failures gracefully and does not create the chat message" do watched_word = Fabricate(:watched_word, action: WatchedWord.actions[:block]) expect { post "/chat/hooks/#{webhook.key}.json", params: { text: "hey #{watched_word.word}" } }.not_to change { ChatMessage.where(chat_channel: chat_channel).count } expect(response.status).to eq(422) expect(response.parsed_body["errors"]).to include( "Sorry, you can't post the word '#{watched_word.word}'; it's not allowed.", ) end it "handles create message failures gracefully if the channel is read only" do chat_channel.update!(status: :read_only) expect { post "/chat/hooks/#{webhook.key}.json", params: { text: "hey this is a message" } }.not_to change { ChatMessage.where(chat_channel: chat_channel).count } expect(response.status).to eq(422) expect(response.parsed_body["errors"]).to include( I18n.t("chat.errors.channel_new_message_disallowed", status: chat_channel.status_name), ) end it "rate limits" do RateLimiter.enable RateLimiter.clear_all! 10.times { post "/chat/hooks/#{webhook.key}.json", params: { text: "A new signup woo!" } } expect(response.status).to eq(200) post "/chat/hooks/#{webhook.key}.json", params: { text: "A new signup woo!" } expect(response.status).to eq(429) end end describe "#create_message_slack_compatible" do it "processes the text param with SlackCompatibility" do expect { post "/chat/hooks/#{webhook.key}/slack.json", params: { text: "A new signup woo <!here>!" } }.to change { ChatMessage.where(chat_channel: chat_channel).count }.by(1) expect(response.status).to eq(200) expect(ChatMessage.last.message).to eq("A new signup woo @here!") end it "processes the attachments param with SlackCompatibility, using the fallback" do payload_data = { attachments: [ { color: "#F4511E", title: "New+alert:+#46353", text: "\"[StatusCake]+https://www.test_notification.com+(StatusCake+Test+Alert):+Down,\"", fallback: "New+alert:+\"[StatusCake]+https://www.test_notification.com+(StatusCake+Test+Alert):+Down,\"+<https://eu.opsg.in/a/i/test/blahguid|46353>\nTags:+", title_link: "https://eu.opsg.in/a/i/test/blahguid", }, ], } expect { post "/chat/hooks/#{webhook.key}/slack.json", params: payload_data }.to change { ChatMessage.where(chat_channel: chat_channel).count }.by(1) expect(ChatMessage.last.message).to eq( "New alert: \"[StatusCake] https://www.test_notification.com (StatusCake Test Alert): Down,\" [46353](https://eu.opsg.in/a/i/test/blahguid)\nTags: ", ) expect { post "/chat/hooks/#{webhook.key}/slack.json", params: { payload: payload_data } }.to change { ChatMessage.where(chat_channel: chat_channel).count }.by(1) end it "can process the payload when it's a JSON string" do payload_data = { attachments: [ { color: "#F4511E", title: "New+alert:+#46353", text: "\"[StatusCake]+https://www.test_notification.com+(StatusCake+Test+Alert):+Down,\"", fallback: "New+alert:+\"[StatusCake]+https://www.test_notification.com+(StatusCake+Test+Alert):+Down,\"+<https://eu.opsg.in/a/i/test/blahguid|46353>\nTags:+", title_link: "https://eu.opsg.in/a/i/test/blahguid", }, ], } expect { post "/chat/hooks/#{webhook.key}/slack.json", params: { payload: payload_data.to_json } }.to change { ChatMessage.where(chat_channel: chat_channel).count }.by(1) expect(ChatMessage.last.message).to eq( "New alert: \"[StatusCake] https://www.test_notification.com (StatusCake Test Alert): Down,\" [46353](https://eu.opsg.in/a/i/test/blahguid)\nTags: ", ) end end end