Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,8 @@ Blue-green deployment via GitHub Actions. Docker multi-arch images (amd64 + arm6
**Production env vars:** `SECRET_KEY_BASE`, `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `SSL_DOMAIN` (or `DISABLE_SSL`), `SENTRY_DSN`

**Data persistence:** Mount volume to `/rails/storage` (SQLite DB + file attachments)

## Pull Request Guidelines

- Do not include a "Test plan" section in PR descriptions
- Keep PR descriptions concise with a summary of changes
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ gem "kredis"
gem "platform_agent"
gem "thruster"
gem "redcarpet"
gem "gemoji"

group :development, :test do
gem "debug"
Expand All @@ -55,6 +56,7 @@ end

group :test do
gem "capybara"
gem "minitest", "< 6.0" # Rails doesn't yet support minitest 6.0's API changes
gem "mocha"
gem "selenium-webdriver"
gem "webmock", require: false
Expand Down
6 changes: 4 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ GEM
geared_pagination (1.2.0)
activesupport (>= 5.0)
addressable (>= 2.5.0)
gemoji (4.1.0)
globalid (1.3.0)
activesupport (>= 6.1)
hashdiff (1.2.0)
Expand Down Expand Up @@ -212,8 +213,7 @@ GEM
mini_magick (5.3.1)
logger
mini_mime (1.1.5)
minitest (6.0.1)
prism (~> 1.5)
minitest (5.27.0)
mocha (2.7.1)
ruby2_keywords (>= 0.0.5)
mono_logger (1.1.2)
Expand Down Expand Up @@ -418,10 +418,12 @@ DEPENDENCIES
debug
faker
geared_pagination
gemoji
image_processing (>= 1.2)
importmap-rails!
jbuilder
kredis
minitest (< 6.0)
mocha
net-http-persistent
ostruct
Expand Down
2 changes: 1 addition & 1 deletion app/models/message.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class Message < ApplicationRecord
include Attachment, Broadcasts, Mentionee, Pagination, Searchable
include Attachment, Broadcasts, Emojification, Mentionee, Pagination, Searchable

belongs_to :room, touch: true
belongs_to :creator, class_name: "User", default: -> { Current.user }
Expand Down
23 changes: 23 additions & 0 deletions app/models/message/emojification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Message::Emojification
extend ActiveSupport::Concern

EMOJI_SHORTCODE_PATTERN = /:([a-z0-9_+-]+):/i

included do
before_save :emojify_body, if: -> { body.changed? }
end

private
def emojify_body
return unless body.body.present?

html = body.body.to_html
emojified_html = html.gsub(EMOJI_SHORTCODE_PATTERN) do |match|
shortcode = $1.downcase
emoji = Emoji.find_by_alias(shortcode)
emoji ? emoji.raw : match
end

self.body = emojified_html if html != emojified_html
end
end
84 changes: 84 additions & 0 deletions test/models/message/emojification_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require "test_helper"

class Message::EmojificationTest < ActiveSupport::TestCase
test "converts shortcode to emoji on create" do
message = rooms(:designers).messages.create!(
body: "I :heart: this!",
client_message_id: "emoji-create",
creator: users(:david)
)

assert_includes message.body.body.to_html, "\u2764"
assert_not_includes message.body.body.to_html, ":heart:"
end

test "converts shortcode to emoji on update" do
message = rooms(:designers).messages.create!(
body: "Hello world",
client_message_id: "emoji-update",
creator: users(:david)
)

message.update!(body: "Hello :wave:")

assert_includes message.body.body.to_html, "\u{1F44B}"
assert_not_includes message.body.body.to_html, ":wave:"
end

test "preserves unknown shortcodes" do
message = rooms(:designers).messages.create!(
body: "This is :notarealcode: right?",
client_message_id: "emoji-unknown",
creator: users(:david)
)

assert_includes message.body.body.to_html, ":notarealcode:"
end

test "converts multiple occurrences of same shortcode" do
message = rooms(:designers).messages.create!(
body: ":heart: and :heart: and :heart:",
client_message_id: "emoji-multiple",
creator: users(:david)
)

assert_equal 3, message.body.body.to_html.scan("\u2764").count
assert_not_includes message.body.body.to_html, ":heart:"
end

test "case insensitive matching" do
message = rooms(:designers).messages.create!(
body: ":HEART: and :Heart: and :heart:",
client_message_id: "emoji-case",
creator: users(:david)
)

assert_equal 3, message.body.body.to_html.scan("\u2764").count
assert_not_includes message.body.body.to_html, ":HEART:"
assert_not_includes message.body.body.to_html, ":Heart:"
assert_not_includes message.body.body.to_html, ":heart:"
end

test "converts shortcodes within HTML content" do
message = rooms(:designers).messages.create!(
body: "<div>Check this :thumbsup:</div>",
client_message_id: "emoji-html",
creator: users(:david)
)

assert_includes message.body.body.to_html, "\u{1F44D}"
assert_not_includes message.body.body.to_html, ":thumbsup:"
end

test "converts multiple different shortcodes" do
message = rooms(:designers).messages.create!(
body: ":heart: :thumbsup: :100:",
client_message_id: "emoji-different",
creator: users(:david)
)

assert_includes message.body.body.to_html, "\u2764"
assert_includes message.body.body.to_html, "\u{1F44D}"
assert_includes message.body.body.to_html, "\u{1F4AF}"
end
end
1 change: 0 additions & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
require_relative "../config/environment"

require "rails/test_help"
require "minitest/unit"
require "mocha/minitest"
require "webmock/minitest"
require "turbo/broadcastable/test_helper"
Expand Down