discourse/plugins/discourse-reactions/spec/requests/topics_controller_spec.rb
Régis Hanol 5b51f071ca
FIX: Include user's own actions in actions_summary even when count is missing (#36865)
When a user had reacted to a post but the undo window had passed and the
post's like_count was 0, the like action was completely omitted from
actions_summary. This happened because the serializer only included
actions when either can_act was true OR count was present.

The reactions plugin depends on likeAction being present to properly
display reactions. When likeAction was null, users couldn't see their
own reactions on certain posts - particularly older posts where
like_count hadn't been synced (common on sites where
discourse_reactions_like_sync_enabled is disabled by default).

The fix adds a third condition: include the action if the user has acted
on it. This ensures users can always see their own actions, even if they
can no longer undo them and the count isn't displayed.

Ref - https://meta.discourse.org/t/391609
2025-12-31 09:05:20 +01:00

75 lines
2.6 KiB
Ruby

# frozen_string_literal: true
describe TopicsController do
fab!(:post)
fab!(:laughing_reaction) { Fabricate(:reaction, post: post, reaction_value: "laughing") }
fab!(:open_mouth_reaction) { Fabricate(:reaction, post: post, reaction_value: "open_mouth") }
fab!(:hugs_reaction) { Fabricate(:reaction, post: post, reaction_value: "hugs") }
fab!(:user_1, :user)
fab!(:user_2, :user)
fab!(:user_3, :user)
fab!(:user_4, :user)
before do
SiteSetting.discourse_reactions_enabled = true
SiteSetting.discourse_reactions_enabled_reactions =
"laughing|open_mouth|cry|angry|thumbsup|hugs"
end
describe "#show" do
context "when user has reacted but like_count is 0 and undo window passed" do
fab!(:reaction) { Fabricate(:reaction, post:) }
fab!(:reaction_user) { Fabricate(:reaction_user, reaction:, user: user_1, post:) }
fab!(:like_action) do
Fabricate(
:post_action,
user: user_1,
post:,
post_action_type_id: PostActionType.types[:like],
created_at: 1.day.ago,
)
end
before do
SiteSetting.post_undo_action_window_mins = 10
post.update_column(:like_count, 0)
end
it "includes the like action in actions_summary with acted flag" do
sign_in(user_1)
get "/t/#{post.topic_id}.json"
expect(response.status).to eq(200)
post_json = response.parsed_body["post_stream"]["posts"].find { |p| p["id"] == post.id }
like_action_summary =
post_json["actions_summary"].find { |a| a["id"] == PostActionType.types[:like] }
expect(like_action_summary).to be_present
expect(like_action_summary["acted"]).to eq(true)
expect(like_action_summary["can_undo"]).to be_nil
end
end
it "does not generate N+1 queries" do
sign_in(user_1)
queries = track_sql_queries { get "/t/#{post.topic_id}.json" }
count = queries.filter { |q| q.include?("reactions") }.size
Fabricate(:reaction_user, reaction: laughing_reaction, user: user_1, post: post)
Fabricate(:reaction_user, reaction: laughing_reaction, user: user_2, post: post)
queries = track_sql_queries { get "/t/#{post.topic_id}.json" }
expect(queries.filter { |q| q.include?("reactions") }.size).to eq(count)
Fabricate(:reaction_user, reaction: hugs_reaction, user: user_3, post: post)
Fabricate(:reaction_user, reaction: open_mouth_reaction, user: user_4, post: post)
queries = track_sql_queries { get "/t/#{post.topic_id}.json" }
expect(queries.filter { |q| q.include?("reactions") }.size).to eq(count)
end
end
end