discourse/plugins/discourse-topic-voting/spec/lib/topic_query_spec.rb
Martin Brennan 062b112e51
DEV: Improve vote queries (#39394)
The change is limited to the topic-voting voter preview and vote-list
queries.

`/voting/who` now only loads a capped preview of active voters instead
of loading every vote and mapping users in Ruby., then limiting on the
client. The cap is 104, archived votes are excluded from the preview,
and the client now uses `topic.vote_count` as the total so the popup can
show “and N more...” without fetching the full voter list.

Also tightened the two vote-list queries so archived votes no longer
appear in `state=my_votes` or `/topics/voted-by/:username`.

Finally, the vote and vote-count models now use `with_deleted` for their
topic association so soft-deleted topics can still be resolved where
those records reference them.
2026-04-21 16:10:28 +10:00

101 lines
3.5 KiB
Ruby
Vendored

# frozen_string_literal: true
describe TopicQuery do
fab!(:user0, :user)
fab!(:category1, :category)
fab!(:topic0) { Fabricate(:topic, category: category1) }
fab!(:topic1) { Fabricate(:topic, category: category1) }
fab!(:vote) { DiscourseTopicVoting::Vote.create!(topic_id: topic1.id, user_id: user0.id) }
fab!(:topic_vote_count) do
DiscourseTopicVoting::TopicVoteCount.create!(topic_id: topic1.id, votes_count: 1)
end
before do
SiteSetting.topic_voting_enabled = true
SiteSetting.topic_voting_show_who_voted = true
end
it "order topic by votes" do
expect(TopicQuery.new(user0, { order: "votes" }).list_latest.topics.map(&:id)).to eq(
[topic1.id, topic0.id],
)
end
it "returns topics voted by user" do
archived_topic = Fabricate(:topic, category: category1)
DiscourseTopicVoting::Vote.create!(
topic_id: archived_topic.id,
user_id: user0.id,
archive: true,
)
expect(TopicQuery.new(user0, { state: "my_votes" }).list_latest.topics.map(&:id)).to eq(
[topic1.id],
)
end
it "orders topic by bumped_at if votes are equal" do
topic2 = Fabricate(:topic, category: category1, bumped_at: 2.hours.ago)
DiscourseTopicVoting::TopicVoteCount.create!(topic_id: topic2.id, votes_count: 2)
topic3 = Fabricate(:topic, category: category1, bumped_at: 3.hours.ago)
topic4 = Fabricate(:topic, category: category1, bumped_at: 1.hour.ago)
opts = { order: "votes", per_page: 2, category: category1.slug }
expect(TopicQuery.new(user0, opts).list_latest.topics.map(&:id)).to eq([topic2.id, topic1.id])
expect(TopicQuery.new(user0, opts.merge(page: 1)).list_latest.topics.map(&:id)).to eq(
[topic0.id, topic4.id],
)
expect(TopicQuery.new(user0, opts.merge(page: 2)).list_latest.topics.map(&:id)).to eq(
[topic3.id],
)
end
describe "#list_hot" do
fab!(:voting_category, :category)
fab!(:non_voting_category, :category)
before { DiscourseTopicVoting::CategorySetting.create!(category: voting_category) }
it "uses vote-trending logic for voting categories" do
user1 = Fabricate(:user)
user2 = Fabricate(:user)
old_topic = Fabricate(:topic, category: voting_category)
DiscourseTopicVoting::Vote.create!(
topic_id: old_topic.id,
user_id: user1.id,
created_at: 60.days.ago,
)
DiscourseTopicVoting::Vote.create!(
topic_id: old_topic.id,
user_id: user2.id,
created_at: 60.days.ago,
)
DiscourseTopicVoting::TopicVoteCount.create!(topic_id: old_topic.id, votes_count: 2)
recent_topic = Fabricate(:topic, category: voting_category)
DiscourseTopicVoting::Vote.create!(
topic_id: recent_topic.id,
user_id: user1.id,
created_at: 1.hour.ago,
)
DiscourseTopicVoting::TopicVoteCount.create!(topic_id: recent_topic.id, votes_count: 1)
result = TopicQuery.new(user0, { category: voting_category.slug }).list_hot.topics.map(&:id)
expect(result.index(recent_topic.id)).to be < result.index(old_topic.id)
end
it "uses standard hot logic for non-voting categories" do
topic_a = Fabricate(:topic, category: non_voting_category)
topic_b = Fabricate(:topic, category: non_voting_category)
TopicHotScore.create!(topic_id: topic_a.id, score: 5.0)
TopicHotScore.create!(topic_id: topic_b.id, score: 10.0)
result =
TopicQuery.new(user0, { category: non_voting_category.slug }).list_hot.topics.map(&:id)
expect(result).to eq([topic_b.id, topic_a.id])
end
end
end