mirror of
https://github.com/discourse/discourse-solved.git
synced 2026-09-18 15:31:34 -04:00
* FEATURE: solved topic auto close setting per category This commit adds per category "solved topics auto close hours" setting. The plugin would use the existing "solved topics auto close hours" setting, except if there was a setting for the relevant category in which case that would take precedence. * minor changes per feedback
213 lines
6.6 KiB
Ruby
213 lines
6.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "rails_helper"
|
|
|
|
RSpec.describe "Managing Posts solved status" do
|
|
let(:topic) { Fabricate(:topic) }
|
|
let(:user) { Fabricate(:trust_level_4) }
|
|
let(:p1) { Fabricate(:post, topic: topic) }
|
|
|
|
before { SiteSetting.allow_solved_on_all_topics = true }
|
|
|
|
describe "auto bump" do
|
|
it "does not automatically bump solved topics" do
|
|
category = Fabricate(:category_with_definition)
|
|
|
|
post = create_post(category: category)
|
|
post2 = create_post(category: category)
|
|
|
|
DiscourseSolved.accept_answer!(post, Discourse.system_user)
|
|
|
|
category.num_auto_bump_daily = 2
|
|
category.save!
|
|
|
|
freeze_time 1.month.from_now
|
|
|
|
expect(category.auto_bump_topic!).to eq(true)
|
|
|
|
freeze_time 13.hours.from_now
|
|
|
|
expect(category.auto_bump_topic!).to eq(false)
|
|
|
|
expect(post.topic.reload.posts_count).to eq(1)
|
|
expect(post2.topic.reload.posts_count).to eq(2)
|
|
end
|
|
end
|
|
|
|
describe "accepting a post as the answer" do
|
|
before do
|
|
sign_in(user)
|
|
SiteSetting.solved_topics_auto_close_hours = 2
|
|
end
|
|
|
|
it "can mark a post as the accepted answer correctly" do
|
|
freeze_time
|
|
|
|
post "/solution/accept.json", params: { id: p1.id }
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(p1.reload.custom_fields["is_accepted_answer"]).to eq("true")
|
|
|
|
topic.reload
|
|
|
|
expect(topic.public_topic_timer.status_type).to eq(TopicTimer.types[:silent_close])
|
|
|
|
expect(topic.custom_fields[DiscourseSolved::AUTO_CLOSE_TOPIC_TIMER_CUSTOM_FIELD].to_i).to eq(
|
|
topic.public_topic_timer.id,
|
|
)
|
|
|
|
expect(topic.public_topic_timer.execute_at).to eq_time(Time.zone.now + 2.hours)
|
|
|
|
expect(topic.public_topic_timer.based_on_last_post).to eq(true)
|
|
end
|
|
|
|
it "gives priority to category's solved_topics_auto_close_hours setting" do
|
|
freeze_time
|
|
custom_auto_close_category = Fabricate(:category)
|
|
topic_2 = Fabricate(:topic, category: custom_auto_close_category)
|
|
post_2 = Fabricate(:post, topic: topic_2)
|
|
custom_auto_close_category.custom_fields["solved_topics_auto_close_hours"] = 4
|
|
custom_auto_close_category.save_custom_fields
|
|
|
|
post "/solution/accept.json", params: { id: post_2.id }
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(post_2.reload.custom_fields["is_accepted_answer"]).to eq("true")
|
|
|
|
topic_2.reload
|
|
|
|
expect(topic_2.public_topic_timer.status_type).to eq(TopicTimer.types[:silent_close])
|
|
|
|
expect(
|
|
topic_2.custom_fields[DiscourseSolved::AUTO_CLOSE_TOPIC_TIMER_CUSTOM_FIELD].to_i,
|
|
).to eq(topic_2.public_topic_timer.id)
|
|
|
|
expect(topic_2.public_topic_timer.execute_at).to eq_time(Time.zone.now + 4.hours)
|
|
|
|
expect(topic_2.public_topic_timer.based_on_last_post).to eq(true)
|
|
end
|
|
|
|
it "sends notifications to correct users" do
|
|
SiteSetting.notify_on_staff_accept_solved = true
|
|
user = Fabricate(:user)
|
|
topic = Fabricate(:topic, user: user)
|
|
post = Fabricate(:post, post_number: 2, topic: topic)
|
|
|
|
op = topic.user
|
|
user = post.user
|
|
|
|
expect { DiscourseSolved.accept_answer!(post, Discourse.system_user) }.to change {
|
|
user.notifications.count
|
|
}.by(1) & change { op.notifications.count }.by(1)
|
|
|
|
notification = user.notifications.last
|
|
expect(notification.notification_type).to eq(Notification.types[:custom])
|
|
expect(notification.topic_id).to eq(post.topic_id)
|
|
expect(notification.post_number).to eq(post.post_number)
|
|
|
|
notification = op.notifications.last
|
|
expect(notification.notification_type).to eq(Notification.types[:custom])
|
|
expect(notification.topic_id).to eq(post.topic_id)
|
|
expect(notification.post_number).to eq(post.post_number)
|
|
end
|
|
|
|
it "does not set a timer when the topic is closed" do
|
|
topic.update!(closed: true)
|
|
post "/solution/accept.json", params: { id: p1.id }
|
|
|
|
expect(response.status).to eq(200)
|
|
|
|
p1.reload
|
|
topic.reload
|
|
|
|
expect(p1.custom_fields["is_accepted_answer"]).to eq("true")
|
|
expect(topic.public_topic_timer).to eq(nil)
|
|
expect(topic.closed).to eq(true)
|
|
end
|
|
|
|
it "works with staff and trashed topics" do
|
|
topic.trash!(Discourse.system_user)
|
|
|
|
post "/solution/accept.json", params: { id: p1.id }
|
|
expect(response.status).to eq(403)
|
|
|
|
sign_in(Fabricate(:admin))
|
|
post "/solution/accept.json", params: { id: p1.id }
|
|
expect(response.status).to eq(200)
|
|
|
|
p1.reload
|
|
expect(p1.custom_fields["is_accepted_answer"]).to eq("true")
|
|
end
|
|
|
|
it "does not allow you to accept a whisper" do
|
|
whisper = Fabricate(:post, topic: topic, post_type: Post.types[:whisper])
|
|
sign_in(Fabricate(:admin))
|
|
|
|
post "/solution/accept.json", params: { id: whisper.id }
|
|
expect(response.status).to eq(403)
|
|
end
|
|
|
|
it "triggers a webhook" do
|
|
Fabricate(:solved_web_hook)
|
|
post "/solution/accept.json", params: { id: p1.id }
|
|
|
|
job_args = Jobs::EmitWebHookEvent.jobs[0]["args"].first
|
|
|
|
expect(job_args["event_name"]).to eq("accepted_solution")
|
|
payload = JSON.parse(job_args["payload"])
|
|
expect(payload["id"]).to eq(p1.id)
|
|
end
|
|
end
|
|
|
|
describe "#unaccept" do
|
|
before { sign_in(user) }
|
|
|
|
describe "when solved_topics_auto_close_hours is enabled" do
|
|
before do
|
|
SiteSetting.solved_topics_auto_close_hours = 2
|
|
DiscourseSolved.accept_answer!(p1, user)
|
|
end
|
|
|
|
it "should unmark the post as solved" do
|
|
expect do post "/solution/unaccept.json", params: { id: p1.id } end.to change {
|
|
topic.reload.public_topic_timer
|
|
}.to(nil)
|
|
|
|
expect(response.status).to eq(200)
|
|
p1.reload
|
|
|
|
expect(p1.custom_fields["is_accepted_answer"]).to eq(nil)
|
|
expect(p1.topic.custom_fields["accepted_answer_post_id"]).to eq(nil)
|
|
end
|
|
end
|
|
|
|
it "triggers a webhook" do
|
|
Fabricate(:solved_web_hook)
|
|
post "/solution/unaccept.json", params: { id: p1.id }
|
|
|
|
job_args = Jobs::EmitWebHookEvent.jobs[0]["args"].first
|
|
|
|
expect(job_args["event_name"]).to eq("unaccepted_solution")
|
|
payload = JSON.parse(job_args["payload"])
|
|
expect(payload["id"]).to eq(p1.id)
|
|
end
|
|
end
|
|
|
|
context "with group moderators" do
|
|
fab!(:group_user) { Fabricate(:group_user) }
|
|
let(:user_gm) { group_user.user }
|
|
let(:group) { group_user.group }
|
|
|
|
before do
|
|
SiteSetting.enable_category_group_moderation = true
|
|
p1.topic.category.update!(reviewable_by_group_id: group.id)
|
|
sign_in(user_gm)
|
|
end
|
|
|
|
it "can accept a solution" do
|
|
post "/solution/accept.json", params: { id: p1.id }
|
|
expect(response.status).to eq(200)
|
|
end
|
|
end
|
|
end
|