FIX: Search bug for status:unsolved returns topics from non-solution enabled categories (#241)

* FIX: Search bug for status:unsolved returns topics from non-solution enabled categories

* fixed rubocop issues
This commit is contained in:
Juan David Martínez Cubillos 2023-06-20 09:52:02 -05:00 committed by GitHub
parent 7b90566b05
commit 4032a1e35f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 146 additions and 15 deletions

View File

@ -76,6 +76,7 @@ SQL
AUTO_CLOSE_TOPIC_TIMER_CUSTOM_FIELD = "solved_auto_close_topic_timer_id" AUTO_CLOSE_TOPIC_TIMER_CUSTOM_FIELD = "solved_auto_close_topic_timer_id"
ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD = "accepted_answer_post_id" ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD = "accepted_answer_post_id"
ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD = "enable_accepted_answers"
def self.accept_answer!(post, acting_user, topic: nil) def self.accept_answer!(post, acting_user, topic: nil)
topic ||= post.topic topic ||= post.topic
@ -502,9 +503,10 @@ SQL
def self.reset_accepted_answer_cache def self.reset_accepted_answer_cache
@@allowed_accepted_cache["allowed"] = begin @@allowed_accepted_cache["allowed"] = begin
Set.new( Set.new(
CategoryCustomField.where(name: "enable_accepted_answers", value: "true").pluck( CategoryCustomField.where(
:category_id, name: ::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD,
), value: "true",
).pluck(:category_id),
) )
end end
end end
@ -586,14 +588,32 @@ SQL
end end
Search.advanced_filter(/status:unsolved/) do |posts| Search.advanced_filter(/status:unsolved/) do |posts|
posts.where( if SiteSetting.allow_solved_on_all_topics
"topics.id NOT IN ( posts.where(
SELECT tc.topic_id "topics.id NOT IN (
FROM topic_custom_fields tc SELECT tc.topic_id
WHERE tc.name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}' AND FROM topic_custom_fields tc
tc.value IS NOT NULL WHERE tc.name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}' AND
)", tc.value IS NOT NULL
) )",
)
else
posts.where(
"topics.id NOT IN (
SELECT tc.topic_id
FROM topic_custom_fields tc
WHERE tc.name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}' AND
tc.value IS NOT NULL
) AND topics.id IN (
SELECT top.id
FROM topics top
INNER JOIN category_custom_fields cc
ON top.category_id = cc.category_id
WHERE cc.name = '#{::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD}' AND
cc.value = 'true'
)",
)
end
end end
end end
@ -655,7 +675,7 @@ SQL
TopicList.preloaded_custom_fields << ::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD TopicList.preloaded_custom_fields << ::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD
end end
if Site.respond_to? :preloaded_category_custom_fields if Site.respond_to? :preloaded_category_custom_fields
Site.preloaded_category_custom_fields << "enable_accepted_answers" Site.preloaded_category_custom_fields << ::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD
end end
if Search.respond_to? :preloaded_topic_custom_fields if Search.respond_to? :preloaded_topic_custom_fields
Search.preloaded_topic_custom_fields << ::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD Search.preloaded_topic_custom_fields << ::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD
@ -696,7 +716,7 @@ SQL
) )
CategoryCustomField.create!( CategoryCustomField.create!(
category_id: solved_category.id, category_id: solved_category.id,
name: "enable_accepted_answers", name: ::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD,
value: "true", value: "true",
) )
puts "discourse-solved enabled on category '#{solved_category.name}' (#{solved_category.id})." puts "discourse-solved enabled on category '#{solved_category.name}' (#{solved_category.id})."
@ -706,7 +726,7 @@ SQL
unless SiteSetting.allow_solved_on_all_topics unless SiteSetting.allow_solved_on_all_topics
solved_category_id = solved_category_id =
CategoryCustomField CategoryCustomField
.where(name: "enable_accepted_answers", value: "true") .where(name: ::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD, value: "true")
.first .first
.category_id .category_id

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
Fabricator(:custom_topic, from: :topic) do
transient :custom_topic_name
transient :value
after_create do |top, transients|
custom_topic =
TopicCustomField.new(
topic_id: top.id,
name: transients[:custom_topic_name],
value: transients[:value],
)
custom_topic.save
end
end

View File

@ -4,7 +4,7 @@ require "rails_helper"
RSpec.describe "Managing Posts solved status" do RSpec.describe "Managing Posts solved status" do
let(:topic) { Fabricate(:topic) } let(:topic) { Fabricate(:topic) }
let(:user) { Fabricate(:trust_level_4) } fab!(:user) { Fabricate(:trust_level_4) }
let(:p1) { Fabricate(:post, topic: topic) } let(:p1) { Fabricate(:post, topic: topic) }
before { SiteSetting.allow_solved_on_all_topics = true } before { SiteSetting.allow_solved_on_all_topics = true }
@ -39,6 +39,103 @@ RSpec.describe "Managing Posts solved status" do
result = Search.execute("carrot") result = Search.execute("carrot")
expect(result.posts.pluck(:id)).to eq([solved_post.id, normal_post.id]) expect(result.posts.pluck(:id)).to eq([solved_post.id, normal_post.id])
end end
describe "#advanced_search" do
fab!(:category_enabled) do
category = Fabricate(:category)
category_custom_field =
CategoryCustomField.new(
category_id: category.id,
name: ::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD,
value: "true",
)
category_custom_field.save
category
end
fab!(:category_disabled) do
category = Fabricate(:category)
category_custom_field =
CategoryCustomField.new(
category_id: category.id,
name: ::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD,
value: "false",
)
category_custom_field.save
category
end
fab!(:topic_unsolved) do
Fabricate(
:custom_topic,
user: user,
category: category_enabled,
custom_topic_name: ::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD,
)
end
fab!(:topic_solved) do
Fabricate(
:custom_topic,
user: user,
category: category_enabled,
custom_topic_name: ::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD,
)
end
fab!(:topic_disabled_1) do
Fabricate(
:custom_topic,
user: user,
category: category_disabled,
custom_topic_name: ::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD,
)
end
fab!(:topic_disabled_2) do
Fabricate(
:custom_topic,
user: user,
category: category_disabled,
custom_topic_name: "another_custom_field",
)
end
fab!(:post_unsolved) { Fabricate(:post, topic: topic_unsolved) }
fab!(:post_solved) do
post = Fabricate(:post, topic: topic_solved)
DiscourseSolved.accept_answer!(post, Discourse.system_user)
post
end
fab!(:post_disabled_1) { Fabricate(:post, topic: topic_disabled_1) }
fab!(:post_disabled_2) { Fabricate(:post, topic: topic_disabled_2) }
before do
SearchIndexer.enable
Jobs.run_immediately!
SearchIndexer.index(topic_unsolved, force: true)
SearchIndexer.index(topic_solved, force: true)
SearchIndexer.index(topic_disabled_1, force: true)
SearchIndexer.index(topic_disabled_2, force: true)
end
after { SearchIndexer.disable }
describe "searches for unsolved topics" do
describe "when allow solved on all topics is disabled" do
before { SiteSetting.allow_solved_on_all_topics = false }
it "only returns posts where 'Allow topic owner and staff to mark a reply as the solution' is enabled and post is not solved" do
result = Search.execute("status:unsolved")
expect(result.posts.pluck(:id)).to match_array([post_unsolved.id])
end
end
describe "when allow solved on all topics is enabled" do
before { SiteSetting.allow_solved_on_all_topics = true }
it "only returns posts where the post is not solved" do
result = Search.execute("status:unsolved")
expect(result.posts.pluck(:id)).to match_array(
[post_unsolved.id, post_disabled_1.id, post_disabled_2.id],
)
end
end
end
end
end end
describe "auto bump" do describe "auto bump" do