Fix avatars failing to be set on XMPP accounts
CI / Test (pull_request) Successful in 32s
Release Drafter / Update release notes draft (pull_request) Successful in 3s

There's a stray `end` that prematurely closes the class
This commit is contained in:
2026-08-10 21:35:28 -06:00
parent d196c161df
commit 1957df3bbd
2 changed files with 106 additions and 2 deletions
@@ -0,0 +1,104 @@
require 'rails_helper'
require 'webmock/rspec'
require 'digest'
RSpec.describe EjabberdManager::SetAvatar, type: :model do
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
let(:fixture_path) { Rails.root.join("spec/fixtures/files/bender.png") }
let(:img_data) do
ImageProcessing::Vips
.source(File.open(fixture_path))
.resize_to_fill(256, 256)
.convert("png")
.call.read
end
let(:sha1_hash) { Digest::SHA1.hexdigest(img_data) }
let(:base64_data) { Base64.strict_encode64(img_data) }
before do
ActiveStorage::Blob.create_and_upload!(
io: File.open(fixture_path),
filename: "bender.png",
content_type: "image/png"
).tap { |blob| user.avatar.attach(blob) }
end
def stub_send_stanza_ok
stub_request(:post, "http://xmpp.example.com/api/send_stanza")
.to_return(status: 200, body: "", headers: {})
end
context "when an avatar is already set and overwrite is false" do
before do
allow(EjabberdManager::GetAvatar).to receive(:call).with(user: user).and_return({ img_base64: "abc", content_type: "image/png" })
stub_send_stanza_ok
end
it "does not send any stanzas" do
described_class.call(user: user)
expect(WebMock).not_to have_requested(:post, "http://xmpp.example.com/api/send_stanza")
end
end
context "when no avatar is set yet" do
let(:sent_stanzas) { [] }
before do
allow(EjabberdManager::GetAvatar).to receive(:call).with(user: user).and_return(nil)
stub_request(:post, "http://xmpp.example.com/api/send_stanza")
.to_return(status: 200, body: "", headers: {})
end
it "publishes the XEP-0084 data and metadata stanzas" do
service = described_class.new(user: user)
allow(service).to receive(:send_stanza) do |payload|
sent_stanzas << payload[:stanza]
double(status: 200)
end
service.call
expect(sent_stanzas.length).to eq(2)
data_stanza = sent_stanzas.find { |s| s.include?("urn:xmpp:avatar:data") }
meta_stanza = sent_stanzas.find { |s| s.include?("urn:xmpp:avatar:metadata") }
expect(data_stanza).to include("from='willherschel@kosmos.org'")
expect(data_stanza).to include("<item id='#{sha1_hash}'>")
expect(data_stanza).to include("<data xmlns='urn:xmpp:avatar:data'>#{base64_data}</data>")
expect(meta_stanza).to include("from='willherschel@kosmos.org'")
expect(meta_stanza).to include("<item id='#{sha1_hash}'>")
expect(meta_stanza).to include("bytes='#{img_data.size}'")
expect(meta_stanza).to include("id='#{sha1_hash}'")
expect(meta_stanza).to include("type='image/png'")
expect(meta_stanza).to include("height='256'")
expect(meta_stanza).to include("width='256'")
end
end
context "when overwrite is true" do
before do
allow(EjabberdManager::GetAvatar).to receive(:call).and_return({ img_base64: "abc", content_type: "image/png" })
stub_send_stanza_ok
end
it "does not check for an existing avatar and sends stanzas" do
described_class.call(user: user, overwrite: true)
expect(EjabberdManager::GetAvatar).not_to have_received(:call)
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/send_stanza").twice
end
end
context "when the ejabberd API returns a non-200 status" do
before do
allow(EjabberdManager::GetAvatar).to receive(:call).with(user: user).and_return(nil)
stub_request(:post, "http://xmpp.example.com/api/send_stanza")
.to_return(status: 500, body: "error", headers: {})
end
it "raises" do
expect { described_class.call(user: user) }.to raise_error(RuntimeError)
end
end
end