0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-11 02:59:07 +08:00
discourse/plugins/discourse-reactions/spec/serializers/topic_view_serializer_spec.rb
Gabriel Grubba b5f7d48840
UX: Ignored users reactions/likes should not show up (#39672)
With this change, a user who is ignoring another no longer sees that
user's likes or reactions: the ignored user is hidden from the
likes/reactions lists, and the like and reaction counts shown to the
ignoring user are adjusted accordingly.

Anonymous viewers and viewers who aren't ignoring anyone see the
original counts.

See it in action in the video:


https://github.com/user-attachments/assets/535e9aaa-0a1c-49eb-a2d4-5fdebf9d7539
2026-05-11 15:32:29 -03:00

201 lines
6.7 KiB
Ruby
Vendored

# frozen_string_literal: true
require_relative "../fabricators/reaction_fabricator"
require_relative "../fabricators/reaction_user_fabricator"
describe TopicViewSerializer do
before { SiteSetting.discourse_reactions_enabled = true }
context "with reactions and shadow like" do
fab!(:user_1, :user)
fab!(:user_2, :user)
fab!(:post_1) { Fabricate(:post, user: user_1) }
fab!(:post_2) { Fabricate(:post, user: user_1, topic: post_1.topic) }
fab!(:otter) { Fabricate(:reaction, post: post_1, reaction_value: "otter") }
fab!(:reaction_user1) { Fabricate(:reaction_user, reaction: otter, user: user_1) }
fab!(:reaction_user2) { Fabricate(:reaction_user, reaction: otter, user: user_2) }
fab!(:like_1) do
Fabricate(
:post_action,
post: post_1,
user: user_1,
post_action_type_id: PostActionType::LIKE_POST_ACTION_ID,
)
end
fab!(:like_2) do
Fabricate(
:post_action,
post: post_1,
user: user_2,
post_action_type_id: PostActionType::LIKE_POST_ACTION_ID,
)
end
let(:topic) { post_1.topic }
let(:topic_view) { TopicView.new(topic) }
it "shows valid reactions and user reactions" do
SiteSetting.discourse_reactions_like_icon = "heart"
SiteSetting.discourse_reactions_enabled_reactions =
"laughing|heart|open_mouth|cry|angry|thumbsup|thumbsdown"
json = TopicViewSerializer.new(topic_view, scope: Guardian.new(user_1), root: false).as_json
expect(json[:valid_reactions]).to eq(
%w[laughing heart open_mouth cry angry thumbsup thumbsdown].to_set,
)
expect(json[:post_stream][:posts][0][:reactions]).to eq(
[{ id: "otter", type: :emoji, count: 2 }],
)
expect(json[:post_stream][:posts][0][:reaction_users_count]).to eq(2)
end
it "doesn't count deleted likes" do
SiteSetting.discourse_reactions_like_icon = "heart"
json = TopicViewSerializer.new(topic_view, scope: Guardian.new(user_2), root: false).as_json
expect(json[:post_stream][:posts][1][:reaction_users_count]).to eq(0)
DiscourseReactions::ReactionManager.new(
reaction_value: "heart",
user: user_2,
post: post_2,
).toggle!
json =
TopicViewSerializer.new(
TopicView.new(topic),
scope: Guardian.new(user_2),
root: false,
).as_json
expect(json[:post_stream][:posts][1][:reaction_users_count]).to eq(1)
DiscourseReactions::ReactionManager.new(
reaction_value: "heart",
user: user_2,
post: post_2,
).toggle!
json =
TopicViewSerializer.new(
TopicView.new(topic),
scope: Guardian.new(user_2),
root: false,
).as_json
expect(json[:post_stream][:posts][1][:reaction_users_count]).to eq(0)
end
end
context "with ignored users" do
fab!(:viewer, :user)
fab!(:other_user, :user)
fab!(:ignored, :user)
fab!(:another_ignored, :user)
fab!(:post_1, :post)
fab!(:post_2) { Fabricate(:post, topic: post_1.topic) }
fab!(:otter) { Fabricate(:reaction, post: post_1, reaction_value: "otter") }
fab!(:heart) { Fabricate(:reaction, post: post_1, reaction_value: "heart") }
fab!(:reaction_user_other) { Fabricate(:reaction_user, reaction: otter, user: other_user) }
fab!(:reaction_user_ignored) { Fabricate(:reaction_user, reaction: otter, user: ignored) }
fab!(:reaction_user_heart_ignored) do
Fabricate(:reaction_user, reaction: heart, user: another_ignored)
end
fab!(:like_other_post_2) do
Fabricate(
:post_action,
post: post_2,
user: other_user,
post_action_type_id: PostActionType::LIKE_POST_ACTION_ID,
)
end
fab!(:like_ignored_post_2) do
Fabricate(
:post_action,
post: post_2,
user: ignored,
post_action_type_id: PostActionType::LIKE_POST_ACTION_ID,
)
end
let(:topic) { post_1.topic }
before do
SiteSetting.discourse_reactions_like_icon = "heart"
SiteSetting.discourse_reactions_enabled_reactions = "otter|heart"
Fabricate(:ignored_user, user: viewer, ignored_user: ignored)
Fabricate(:ignored_user, user: viewer, ignored_user: another_ignored)
end
def serialize_for(user)
TopicViewSerializer.new(
TopicView.new(topic, user),
scope: Guardian.new(user),
root: false,
).as_json
end
it "excludes ignored users from preloaded :reactions" do
json = serialize_for(viewer)
posts = json[:post_stream][:posts]
expect(posts[0][:reactions]).to contain_exactly({ id: "otter", type: :emoji, count: 1 })
expect(posts[1][:reactions]).to contain_exactly({ id: "heart", type: :emoji, count: 1 })
end
it "excludes ignored users from preloaded :reaction_users_count" do
json = serialize_for(viewer)
posts = json[:post_stream][:posts]
expect(posts[0][:reaction_users_count]).to eq(1)
expect(posts[1][:reaction_users_count]).to eq(1)
end
it "still shows global counts for anonymous viewers" do
json = TopicViewSerializer.new(TopicView.new(topic), scope: Guardian.new, root: false).as_json
posts = json[:post_stream][:posts]
expect(posts[0][:reactions]).to contain_exactly(
{ id: "otter", type: :emoji, count: 2 },
{ id: "heart", type: :emoji, count: 1 },
)
expect(posts[0][:reaction_users_count]).to eq(3)
expect(posts[1][:reaction_users_count]).to eq(2)
end
it "still shows global counts for viewers with no ignored users" do
json = serialize_for(other_user)
posts = json[:post_stream][:posts]
expect(posts[0][:reactions]).to contain_exactly(
{ id: "otter", type: :emoji, count: 2 },
{ id: "heart", type: :emoji, count: 1 },
)
expect(posts[0][:reaction_users_count]).to eq(3)
expect(posts[1][:reaction_users_count]).to eq(2)
end
end
describe "only shadow like" do
fab!(:user_1, :user)
fab!(:post_1) { Fabricate(:post, user: user_1) }
fab!(:like_1) do
Fabricate(
:post_action,
post: post_1,
user: user_1,
post_action_type_id: PostActionType::LIKE_POST_ACTION_ID,
)
end
let(:topic) { post_1.topic }
let(:topic_view) { TopicView.new(topic) }
it "shows valid reactions and user reactions" do
SiteSetting.discourse_reactions_like_icon = "heart"
json = TopicViewSerializer.new(topic_view, scope: Guardian.new(user_1), root: false).as_json
expect(json[:post_stream][:posts][0][:reactions]).to eq(
[{ id: "heart", type: :emoji, count: 1 }],
)
expect(json[:post_stream][:posts][0][:reaction_users_count]).to eq(1)
end
end
end