discourse/spec/requests/post_action_users_controller_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

298 lines
9.6 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe PostActionUsersController do
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
let(:post) { Fabricate(:post, user: sign_in(user)) }
describe "#index" do
describe "when limit params is invalid" do
include_examples "invalid limit params",
"/post_action_users.json",
described_class::INDEX_LIMIT
end
it "does not include total_rows_post_action_users for restricted action types" do
notify_mod = PostActionType.types[:notify_moderators]
PostActionCreator.new(post.user, post, notify_mod, message: "first report").perform
PostActionCreator.new(
Fabricate(:user, refresh_auto_groups: true),
post,
notify_mod,
message: "second report",
).perform
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: notify_mod,
limit: 1,
}
expect(response.status).to eq(200)
expect(response.parsed_body["post_action_users"].map { |u| u["id"] }).to eq([user.id])
expect(response.parsed_body["total_rows_post_action_users"]).to be_nil
end
it "includes total_rows_post_action_users for restricted action types when staff" do
notify_mod = PostActionType.types[:notify_moderators]
PostActionCreator.new(post.user, post, notify_mod, message: "first report").perform
PostActionCreator.new(
Fabricate(:user, refresh_auto_groups: true),
post,
notify_mod,
message: "second report",
).perform
sign_in(Fabricate(:admin))
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: notify_mod,
limit: 1,
}
expect(response.status).to eq(200)
expect(response.parsed_body["post_action_users"].map { |u| u["id"] }).to eq([user.id])
expect(response.parsed_body["total_rows_post_action_users"]).to eq(2)
end
end
context "with render" do
it "always allows you to see your own actions" do
notify_mod = PostActionType.types[:notify_moderators]
PostActionCreator.new(
post.user,
post,
notify_mod,
message: "well something is wrong here!",
).perform
PostActionCreator.new(
Fabricate(:user),
post,
notify_mod,
message: "well something is not wrong here!",
).perform
get "/post_action_users.json", params: { id: post.id, post_action_type_id: notify_mod }
expect(response.status).to eq(200)
users = response.parsed_body["post_action_users"]
expect(users.length).to eq(1)
expect(users[0]["id"]).to eq(post.user.id)
end
end
it "raises an error without an id" do
get "/post_action_users.json", params: { post_action_type_id: PostActionType.types[:like] }
expect(response.status).to eq(400)
end
it "raises an error without a post action type" do
get "/post_action_users.json", params: { id: post.id }
expect(response.status).to eq(400)
end
it "fails when the user doesn't have permission to see the post" do
post.trash!
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response).to be_forbidden
end
it "raises an error when anon tries to look at an invalid action" do
get "/post_action_users.json",
params: {
id: Fabricate(:post).id,
post_action_type_id: PostActionType.types[:notify_moderators],
}
expect(response).to be_forbidden
end
it "succeeds" do
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
end
it "will return an unknown attribute for muted users" do
muted_user = Fabricate(:user)
PostActionCreator.like(muted_user, post)
regular_user = Fabricate(:user)
PostActionCreator.like(regular_user, post)
Fabricate(:muted_user, user: user, muted_user: muted_user)
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
json_users = response.parsed_body["post_action_users"]
expect(json_users.find { |u| u["id"] == regular_user.id }["unknown"]).to be_blank
expect(json_users.find { |u| u["id"] == muted_user.id }["unknown"]).to eq(true)
end
it "filters out ignored users from the post action user list" do
ignored_user = Fabricate(:user)
PostActionCreator.like(ignored_user, post)
regular_user = Fabricate(:user)
PostActionCreator.like(regular_user, post)
Fabricate(:ignored_user, user: user, ignored_user: ignored_user)
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
user_ids = response.parsed_body["post_action_users"].map { |u| u["id"] }
expect(user_ids).to include(regular_user.id)
expect(user_ids).not_to include(ignored_user.id)
end
it "still shows ignored users to anonymous viewers" do
ignorer = Fabricate(:user)
ignored_user = Fabricate(:user)
PostActionCreator.like(ignored_user, post)
Fabricate(:ignored_user, user: ignorer, ignored_user: ignored_user)
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
user_ids = response.parsed_body["post_action_users"].map { |u| u["id"] }
expect(user_ids).to include(ignored_user.id)
end
it "reports the filtered total in total_rows_post_action_users" do
stub_const(described_class, "INDEX_LIMIT", 2) do
ignored_user = Fabricate(:user)
PostActionCreator.like(ignored_user, post)
3.times { PostActionCreator.like(Fabricate(:user), post) }
Fabricate(:ignored_user, user: user, ignored_user: ignored_user)
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
limit: 2,
}
expect(response.status).to eq(200)
expect(response.parsed_body["total_rows_post_action_users"]).to eq(3)
end
end
it "does not hide users from the like list when they are not in the actor's PM allowlist" do
user_not_in_allowlist = Fabricate(:user)
user_in_allowlist = Fabricate(:user)
PostActionCreator.like(user_not_in_allowlist, post)
PostActionCreator.like(user_in_allowlist, post)
user.user_option.update!(enable_allowed_pm_users: true)
AllowedPmUser.create!(user: user, allowed_pm_user: user_in_allowlist)
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
json_users = response.parsed_body["post_action_users"]
expect(json_users.find { |u| u["id"] == user_not_in_allowlist.id }).to be_present
expect(json_users.find { |u| u["id"] == user_in_allowlist.id }).to be_present
expect(json_users.find { |u| u["id"] == user_not_in_allowlist.id }["unknown"]).to be_blank
expect(json_users.find { |u| u["id"] == user_in_allowlist.id }["unknown"]).to be_blank
end
it "paginates post actions" do
user_ids = []
5.times do
user = Fabricate(:user)
user_ids << user["id"]
PostActionCreator.like(user, post)
end
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
page: 1,
limit: 2,
}
users = response.parsed_body["post_action_users"]
total = response.parsed_body["total_rows_post_action_users"]
expect(users.length).to eq(2)
expect(users.map { |u| u["id"] }).to eq(user_ids[2..3])
expect(total).to eq(5)
end
it "returns no users when the action type id is invalid" do
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: "invalid_action_type",
}
expect(response.status).to eq(200)
users = response.parsed_body["post_action_users"]
total = response.parsed_body["total_rows_post_action_users"]
expect(users.length).to eq(0)
expect(total).to be_nil
end
describe "when a plugin registers the :post_action_users_list modifier" do
before do
@post_action_1 = PostActionCreator.like(Fabricate(:user), post).post_action
@post_action_2 = PostActionCreator.like(Fabricate(:user), post).post_action
end
after { DiscoursePluginRegistry.clear_modifiers! }
it "allows the plugin to modify the post action query" do
excluded_post_action_ids = [@post_action_1.id]
Plugin::Instance
.new
.register_modifier(:post_action_users_list) do |query, modifier_post|
expect(modifier_post.id).to eq(post.id)
query.where.not(post_actions: { id: excluded_post_action_ids })
end
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
expect(response.parsed_body["post_action_users"].count).to eq(1)
DiscoursePluginRegistry.clear_modifiers!
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
expect(response.parsed_body["post_action_users"].count).to eq(2)
end
end
end