Files
discourse/plugins/chat/spec/services/update_user_last_read_spec.rb
Loïc Guitaut 5f4623ba47 DEV: Refactor UpdateUserLastRead a little
We’re now using `contract` as the first step and validations for
mandatory parameters have been added.

To simplify specs a bit, we only assert the service contract is run as
expected without testing each validation case. We’re now testing the
contract itself in isolation.
2023-02-13 17:03:41 +01:00

120 lines
3.5 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
RSpec.describe Chat::Service::UpdateUserLastRead do
describe Chat::Service::UpdateUserLastRead::Contract, type: :model do
it { is_expected.to validate_presence_of :user_id }
it { is_expected.to validate_presence_of :channel_id }
it { is_expected.to validate_presence_of :message_id }
end
describe ".call" do
subject(:result) { described_class.call(params) }
fab!(:current_user) { Fabricate(:user) }
fab!(:channel) { Fabricate(:chat_channel) }
fab!(:membership) do
Fabricate(:user_chat_channel_membership, user: current_user, chat_channel: channel)
end
fab!(:message_1) { Fabricate(:chat_message, chat_channel: membership.chat_channel) }
let(:guardian) { Guardian.new(current_user) }
let(:params) do
{
guardian: guardian,
user_id: current_user.id,
channel_id: channel.id,
message_id: message_1.id,
}
end
context "when params are not valid" do
before { params.delete(:user_id) }
it { is_expected.to fail_a_contract }
end
context "when params are valid" do
context "when user has no membership" do
before { membership.destroy! }
it { is_expected.to fail_to_find_a_model(:membership) }
end
context "when user cant access the channel" do
fab!(:membership) do
Fabricate(
:user_chat_channel_membership,
user: current_user,
chat_channel: Fabricate(:private_category_channel),
)
end
before { params[:channel_id] = membership.chat_channel.id }
it { is_expected.to fail_a_policy(:invalid_access) }
end
context "when message_id is older than membership's last_read_message_id" do
before do
params[:message_id] = -2
membership.update!(last_read_message_id: -1)
end
it { is_expected.to fail_a_policy(:ensure_message_id_recency) }
end
context "when message doesnt exist" do
before do
params[:message_id] = 2
membership.update!(last_read_message_id: 1)
end
it { is_expected.to fail_a_policy(:ensure_message_exists) }
end
context "when everything is fine" do
fab!(:notification) do
Fabricate(
:notification,
notification_type: Notification.types[:chat_mention],
user: current_user,
)
end
let(:messages) { MessageBus.track_publish { result } }
before do
Jobs.run_immediately!
ChatMention.create!(
notification: notification,
user: current_user,
chat_message: message_1,
)
end
it "sets the service result as successful" do
expect(result).to be_a_success
end
it "updates the last_read message id" do
expect { result }.to change { membership.reload.last_read_message_id }.to(message_1.id)
end
it "marks existing notifications related to the message as read" do
expect { result }.to change {
Notification.where(
notification_type: Notification.types[:chat_mention],
user: current_user,
read: false,
).count
}.by(-1)
end
it "publishes new last read to clients" do
expect(messages.map(&:channel)).to include("/chat/user-tracking-state/#{current_user.id}")
end
end
end
end
end