mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
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.
120 lines
3.5 KiB
Ruby
120 lines
3.5 KiB
Ruby
# 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 can’t 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 doesn’t 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
|