Merge branch 'post-messages-with-unreadable-attachments' into bound-attachment-previews

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bj8KnxpTf9sj2Ysa8aLAVa
This commit is contained in:
Marcello Costagliola
2026-10-06 15:20:56 +02:00
3 changed files with 36 additions and 0 deletions
+3
View File
@@ -30,6 +30,7 @@ module Message::Attachment
attachment&.analyze
end
# A file that ffmpeg or libvips can't decode is still the message: post it without a preview.
def process_attachment_thumbnail
case
when attachment.video?
@@ -37,5 +38,7 @@ module Message::Attachment
when attachment.representable?
attachment.representation(:thumb).processed
end
rescue ActiveStorage::PreviewError, Vips::Error => error
Rails.logger.warn "Posted #{attachment.filename} without a preview: #{error.class}: #{error.message.lines.first&.chomp}"
end
end
@@ -57,6 +57,18 @@ class MessagesControllerTest < ActionDispatch::IntegrationTest
end
end
test "creating a message with an image that can't be decoded broadcasts the message to the room" do
webp = Vips::Image.new_from_file(file_fixture("moon.jpg").to_s).webpsave_buffer
broken = Rack::Test::UploadedFile.new(StringIO.new(webp.byteslice(0, webp.bytesize / 2)), "image/webp", original_filename: "broken.webp")
post room_messages_url(@room, format: :turbo_stream), params: { message: { attachment: broken, client_message_id: 999 } }
assert_response :success
assert_rendered_turbo_stream_broadcast @room, :messages, action: "append", target: [ @room, :messages ] do
assert_select ".message__body a[href*='broken.webp']"
end
end
test "creating a message broadcasts unread room to each member" do
@room.users.each do |member|
assert_broadcasts UnreadRoomsChannel.stream_name_for(member.id), 1 do
+21
View File
@@ -19,6 +19,20 @@ class Message::AttachmentTest < ActiveSupport::TestCase
assert_equal message.plain_text_body, "moon.jpg"
end
test "creating a message keeps an image that can't be decoded" do
webp = Vips::Image.new_from_file(file_fixture("moon.jpg").to_s).webpsave_buffer
message = create_unreadable_attachment_message(webp.byteslice(0, webp.bytesize / 2), "broken.webp")
assert_equal "broken.webp", message.reload.attachment.filename.to_s
assert_nil message.attachment.representation(:thumb).image
end
test "creating a message keeps a video that can't be decoded" do
message = create_unreadable_attachment_message(file_fixture("alpha-centuri.mov").binread(64), "broken.mov")
assert_equal "broken.mov", message.reload.attachment.filename.to_s
assert_not message.attachment.preview(format: :webp).image.attached?
end
private
def create_attachment_message(file, content_type)
@@ -27,4 +41,11 @@ class Message::AttachmentTest < ActiveSupport::TestCase
client_message_id: "message",
attachment: fixture_file_upload(file, content_type)
end
def create_unreadable_attachment_message(content, filename)
rooms(:hq).messages.create_with_attachment! \
creator: users(:david),
client_message_id: "message",
attachment: { io: StringIO.new(content), filename: filename }
end
end