# frozen_string_literal: true require "rails_helper" describe ChatMessage do fab!(:message) { Fabricate(:chat_message, message: "hey friend, what's up?!") } describe ".cook" do it "does not support HTML tags" do cooked = ChatMessage.cook("
<h1>test</h1>
") end it "does not support headings" do cooked = ChatMessage.cook("## heading 2") expect(cooked).to eq("## heading 2
") end it "does not support horizontal rules" do cooked = ChatMessage.cook("---") expect(cooked).to eq("---
") end it "supports backticks rule" do cooked = ChatMessage.cook("`test`") expect(cooked).to eq("test
something = test
COOKED
end
it "supports fence rule with language support" do
cooked = ChatMessage.cook(<<~RAW)
```ruby
Widget.triangulate(argument: "no u")
```
RAW
expect(cooked).to eq(<<~COOKED.chomp)
Widget.triangulate(argument: "no u")
COOKED
end
it "supports code rule" do
cooked = ChatMessage.cook(" something = test")
expect(cooked).to eq("something = test\n
")
end
it "supports blockquote rule" do
cooked = ChatMessage.cook("> a quote")
expect(cooked).to eq("\n") end it "supports quote bbcode" do topic = Fabricate(:topic, title: "Some quotable topic") post = Fabricate(:post, topic: topic) SiteSetting.external_system_avatars_enabled = false avatar_src = "//test.localhost#{User.system_avatar_template(post.user.username).gsub("{size}", "40")}" cooked = ChatMessage.cook(<<~RAW) [quote="#{post.user.username}, post:#{post.post_number}, topic:#{topic.id}"] Mark me...this will go down in history. [/quote] RAW expect(cooked).to eq(<<~COOKED.chomp) COOKED end it "supports chat quote bbcode" do chat_channel = Fabricate(:category_channel, name: "testchannel") user = Fabricate(:user, username: "chatbbcodeuser") user2 = Fabricate(:user, username: "otherbbcodeuser") avatar_src = "//test.localhost#{User.system_avatar_template(user.username).gsub("{size}", "40")}" avatar_src2 = "//test.localhost#{User.system_avatar_template(user2.username).gsub("{size}", "40")}" msg1 = Fabricate( :chat_message, chat_channel: chat_channel, message: "this is the first message", user: user, ) msg2 = Fabricate( :chat_message, chat_channel: chat_channel, message: "and another cool one", user: user2, ) other_messages_to_quote = [msg1, msg2] cooked = ChatMessage.cook( ChatTranscriptService.new( chat_channel, Fabricate(:user), messages_or_ids: other_messages_to_quote.map(&:id), ).generate_markdown, ) expect(cooked).to eq(<<~COOKED.chomp)a quote
\n
test
bold
") end it "supports link markdown rule" do chat_message = Fabricate(:chat_message, message: "[test link](https://www.example.com)") expect(chat_message.cooked).to eq( "", ) end it "supports table markdown plugin" do cooked = ChatMessage.cook(<<~RAW) | Command | Description | | --- | --- | | git status | List all new or modified files | RAW expected = <<~COOKEDCommand | Description |
---|---|
git status | List all new or modified files |
@mention
") end it "supports category-hashtag plugin" do category = Fabricate(:category) cooked = ChatMessage.cook("##{category.slug}") expect(cooked).to eq( "", ) end it "supports censored plugin" do watched_word = Fabricate(:watched_word, action: WatchedWord.actions[:censor]) cooked = ChatMessage.cook(watched_word.word) expect(cooked).to eq("■■■■■
") end it "includes links in pretty text excerpt if the raw message is a single link and the PrettyText excerpt is blank" do message = Fabricate.build( :chat_message, message: "https://twitter.com/EffinBirds/status/1518743508378697729", ) expect(message.excerpt).to eq("https://twitter.com/EffinBirds/status/1518743508378697729") message = Fabricate.build( :chat_message, message: "https://twitter.com/EffinBirds/status/1518743508378697729", cooked: <<~COOKED, \n COOKED ) expect(message.excerpt).to eq("https://twitter.com/EffinBirds/status/1518743508378697729") message = Fabricate.build( :chat_message, message: "wow check out these birbs https://twitter.com/EffinBirds/status/1518743508378697729", ) expect(message.excerpt).to eq( "wow check out these birbs https://twitter.com/Effi…", ) end it "returns an empty string if PrettyText.excerpt returns empty string" do message = Fabricate(:chat_message, message: <<~MSG) [quote="martin, post:30, topic:3179, full:true"] This is a real **quote** topic with some *markdown* in it I can quote. [/quote] MSG expect(message.excerpt).to eq("") end it "excerpts upload file name if message is empty" do gif = Fabricate(:upload, original_filename: "cat.gif", width: 400, height: 300, extension: "gif") message = Fabricate(:chat_message, message: "") ChatUpload.create(chat_message: message, upload: gif) expect(message.excerpt).to eq "cat.gif" end it "supports autolink with <>" do cooked = ChatMessage.cook("https://github.com/discourse/discourse-chat/pull/468
", ) end it "supports lists" do cooked = ChatMessage.cook(<<~MSG) wow look it's a list * item 1 * item 2 MSG expect(cooked).to eq(<<~HTML.chomp)wow look it's a list
this is a replace test
HTML end it "supports spoilers" do if SiteSetting.respond_to?(:spoiler_enabled) && SiteSetting.spoiler_enabled cooked = ChatMessage.cook("[spoiler]the planet of the apes was earth all along[/spoiler]") expect(cooked).to eq( "the planet of the apes was earth all along
\n<h1>@#{user.username}</h1>
") end end end describe ".to_markdown" do it "renders the message without uploads" do expect(message.to_markdown).to eq("hey friend, what's up?!") end it "renders the message with uploads" do image = Fabricate( :upload, original_filename: "test_image.jpg", width: 400, height: 300, extension: "jpg", ) image2 = Fabricate(:upload, original_filename: "meme.jpg", width: 10, height: 10, extension: "jpg") ChatUpload.create(chat_message: message, upload: image) ChatUpload.create(chat_message: message, upload: image2) expect(message.to_markdown).to eq(<<~MSG.chomp) hey friend, what's up?! ![test_image.jpg|400x300](#{image.short_url}) ![meme.jpg|10x10](#{image2.short_url}) MSG end end describe ".push_notification_excerpt" do it "truncates to 400 characters" do message = ChatMessage.new(message: "Hello, World!" * 40) expect(message.push_notification_excerpt.size).to eq(400) end it "encodes emojis" do message = ChatMessage.new(message: ":grinning:") expect(message.push_notification_excerpt).to eq("😀") end end describe "blocking duplicate messages" do fab!(:channel) { Fabricate(:chat_channel, user_count: 10) } fab!(:user1) { Fabricate(:user) } fab!(:user2) { Fabricate(:user) } before { SiteSetting.chat_duplicate_message_sensitivity = 1 } it "blocks duplicate messages for the message, channel user, and message age requirements" do Fabricate(:chat_message, message: "this is duplicate", chat_channel: channel, user: user1) message = ChatMessage.new(message: "this is duplicate", chat_channel: channel, user: user2) message.validate_message(has_uploads: false) expect(message.errors.full_messages).to include(I18n.t("chat.errors.duplicate_message")) end end describe "#destroy" do it "nullify messages with in_reply_to_id to this destroyed message" do message_1 = Fabricate(:chat_message) message_2 = Fabricate(:chat_message, in_reply_to_id: message_1.id) message_3 = Fabricate(:chat_message, in_reply_to_id: message_2.id) expect(message_2.in_reply_to_id).to eq(message_1.id) message_1.destroy! expect(message_2.reload.in_reply_to_id).to be_nil expect(message_3.reload.in_reply_to_id).to eq(message_2.id) end it "destroys chat_message_revisions" do message_1 = Fabricate(:chat_message) revision_1 = Fabricate(:chat_message_revision, chat_message: message_1) message_1.destroy! expect { revision_1.reload }.to raise_error(ActiveRecord::RecordNotFound) end it "destroys chat_message_reactions" do message_1 = Fabricate(:chat_message) reaction_1 = Fabricate(:chat_message_reaction, chat_message: message_1) message_1.destroy! expect { reaction_1.reload }.to raise_error(ActiveRecord::RecordNotFound) end it "destroys chat_mention" do message_1 = Fabricate(:chat_message) mention_1 = Fabricate(:chat_mention, chat_message: message_1) message_1.destroy! expect { mention_1.reload }.to raise_error(ActiveRecord::RecordNotFound) end it "destroys chat_webhook_event" do message_1 = Fabricate(:chat_message) webhook_1 = Fabricate(:chat_webhook_event, chat_message: message_1) message_1.destroy! expect { webhook_1.reload }.to raise_error(ActiveRecord::RecordNotFound) end it "destroys chat_uploads" do message_1 = Fabricate(:chat_message) chat_upload_1 = Fabricate(:chat_upload, chat_message: message_1) message_1.destroy! expect { chat_upload_1.reload }.to raise_error(ActiveRecord::RecordNotFound) end describe "bookmarks" do before { Bookmark.register_bookmarkable(ChatMessageBookmarkable) } it "destroys bookmarks" do message_1 = Fabricate(:chat_message) bookmark_1 = Fabricate(:bookmark, bookmarkable: message_1) message_1.destroy! expect { bookmark_1.reload }.to raise_error(ActiveRecord::RecordNotFound) end end end end