2019-04-29 20:27:42 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
RSpec.describe Reviewable, type: :model do
|
2022-07-27 06:21:10 -04:00
|
|
|
describe ".create" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:admin) { Fabricate(:admin) }
|
|
|
|
fab!(:user) { Fabricate(:user) }
|
2019-01-03 12:03:01 -05:00
|
|
|
|
|
|
|
let(:reviewable) { Fabricate.build(:reviewable, created_by: admin) }
|
|
|
|
|
|
|
|
it "can create a reviewable object" do
|
|
|
|
expect(reviewable).to be_present
|
|
|
|
expect(reviewable.pending?).to eq(true)
|
|
|
|
expect(reviewable.created_by).to eq(admin)
|
|
|
|
|
|
|
|
expect(reviewable.editable_for(Guardian.new(admin))).to be_blank
|
|
|
|
|
|
|
|
expect(reviewable.payload).to be_present
|
|
|
|
expect(reviewable.version).to eq(0)
|
|
|
|
expect(reviewable.payload['name']).to eq('bandersnatch')
|
|
|
|
expect(reviewable.payload['list']).to eq([1, 2, 3])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "can add a target" do
|
|
|
|
reviewable.target = user
|
|
|
|
reviewable.save!
|
|
|
|
|
|
|
|
expect(reviewable.target_type).to eq('User')
|
|
|
|
expect(reviewable.target_id).to eq(user.id)
|
|
|
|
expect(reviewable.target).to eq(user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-27 06:21:10 -04:00
|
|
|
describe ".needs_review!" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:admin) { Fabricate(:admin) }
|
|
|
|
fab!(:user) { Fabricate(:user) }
|
2019-01-03 12:03:01 -05:00
|
|
|
|
|
|
|
it "will return a new reviewable the first them, and re-use the second time" do
|
|
|
|
r0 = ReviewableUser.needs_review!(target: user, created_by: admin)
|
|
|
|
expect(r0).to be_present
|
|
|
|
|
|
|
|
r0.update_column(:status, Reviewable.statuses[:approved])
|
|
|
|
|
|
|
|
r1 = ReviewableUser.needs_review!(target: user, created_by: admin)
|
|
|
|
expect(r1.id).to eq(r0.id)
|
|
|
|
expect(r1.pending?).to eq(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "will add a topic and category from a post" do
|
|
|
|
post = Fabricate(:post)
|
|
|
|
reviewable = ReviewableFlaggedPost.needs_review!(target: post, created_by: Fabricate(:user))
|
|
|
|
expect(reviewable.topic).to eq(post.topic)
|
|
|
|
expect(reviewable.category).to eq(post.topic.category)
|
|
|
|
end
|
|
|
|
|
2019-05-01 11:36:48 -04:00
|
|
|
it "will update the category if the topic category changes" do
|
|
|
|
post = Fabricate(:post)
|
|
|
|
moderator = Fabricate(:moderator)
|
|
|
|
reviewable = PostActionCreator.spam(moderator, post).reviewable
|
|
|
|
expect(reviewable.category).to eq(post.topic.category)
|
|
|
|
new_cat = Fabricate(:category)
|
|
|
|
PostRevisor.new(post).revise!(moderator, category_id: new_cat.id)
|
|
|
|
expect(post.topic.reload.category).to eq(new_cat)
|
|
|
|
expect(reviewable.reload.category).to eq(new_cat)
|
|
|
|
end
|
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
it "can create multiple objects with a NULL target" do
|
|
|
|
r0 = ReviewableQueuedPost.needs_review!(created_by: admin, payload: { raw: 'hello world I am a post' })
|
|
|
|
expect(r0).to be_present
|
|
|
|
r0.update_column(:status, Reviewable.statuses[:approved])
|
|
|
|
|
|
|
|
r1 = ReviewableQueuedPost.needs_review!(created_by: admin, payload: { raw: "another post's contents" })
|
|
|
|
|
|
|
|
expect(ReviewableQueuedPost.count).to eq(2)
|
|
|
|
expect(r1.id).not_to eq(r0.id)
|
|
|
|
expect(r1.pending?).to eq(true)
|
|
|
|
expect(r0.pending?).to eq(false)
|
|
|
|
end
|
2021-07-07 12:45:00 -04:00
|
|
|
|
|
|
|
it "will create a new reviewable when an existing reviewable exists the same target with different type" do
|
|
|
|
r0 = Fabricate(:reviewable_queued_post)
|
|
|
|
r0.perform(admin, :approve_post)
|
|
|
|
|
|
|
|
r1 = ReviewableFlaggedPost.needs_review!(created_by: admin, target: r0.target)
|
|
|
|
expect(r1.pending?).to eq(true)
|
|
|
|
end
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
|
2022-07-27 06:21:10 -04:00
|
|
|
describe ".list_for" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:user) { Fabricate(:user) }
|
2019-01-03 12:03:01 -05:00
|
|
|
|
|
|
|
it "returns an empty list for nil user" do
|
|
|
|
expect(Reviewable.list_for(nil)).to eq([])
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with a pending item" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:post) { Fabricate(:post) }
|
2019-01-03 12:03:01 -05:00
|
|
|
let(:reviewable) { Fabricate(:reviewable, target: post) }
|
|
|
|
|
|
|
|
it "works with the reviewable by moderator flag" do
|
|
|
|
reviewable.reviewable_by_moderator = true
|
|
|
|
reviewable.save!
|
|
|
|
|
|
|
|
expect(Reviewable.list_for(user, status: :pending)).to be_empty
|
|
|
|
user.update_column(:moderator, true)
|
|
|
|
expect(Reviewable.list_for(user, status: :pending)).to eq([reviewable])
|
|
|
|
|
|
|
|
# Admins can review everything
|
|
|
|
user.update_columns(moderator: false, admin: true)
|
|
|
|
expect(Reviewable.list_for(user, status: :pending)).to eq([reviewable])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "works with the reviewable by group" do
|
2020-07-14 12:36:19 -04:00
|
|
|
SiteSetting.enable_category_group_moderation = true
|
2019-01-03 12:03:01 -05:00
|
|
|
group = Fabricate(:group)
|
|
|
|
reviewable.reviewable_by_group_id = group.id
|
|
|
|
reviewable.save!
|
|
|
|
|
|
|
|
expect(Reviewable.list_for(user, status: :pending)).to be_empty
|
|
|
|
gu = GroupUser.create!(group_id: group.id, user_id: user.id)
|
|
|
|
expect(Reviewable.list_for(user, status: :pending)).to eq([reviewable])
|
|
|
|
|
|
|
|
# Admins can review everything
|
|
|
|
gu.destroy
|
|
|
|
user.update_columns(moderator: false, admin: true)
|
|
|
|
expect(Reviewable.list_for(user, status: :pending)).to eq([reviewable])
|
|
|
|
end
|
|
|
|
|
2019-04-17 17:12:32 -04:00
|
|
|
it "doesn't allow review by group when disabled" do
|
2020-07-14 12:36:19 -04:00
|
|
|
SiteSetting.enable_category_group_moderation = false
|
2019-04-17 17:12:32 -04:00
|
|
|
group = Fabricate(:group)
|
|
|
|
reviewable.reviewable_by_group_id = group.id
|
|
|
|
reviewable.save!
|
|
|
|
|
|
|
|
GroupUser.create!(group_id: group.id, user_id: user.id)
|
|
|
|
expect(Reviewable.list_for(user, status: :pending)).to be_blank
|
|
|
|
end
|
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
context 'as an admin' do
|
2019-01-03 12:03:01 -05:00
|
|
|
before { user.update_columns(moderator: false, admin: true) }
|
|
|
|
|
|
|
|
it 'can filter by the target_created_by_id attribute' do
|
|
|
|
different_reviewable = Fabricate(:reviewable)
|
|
|
|
reviewables = Reviewable.list_for(user, username: different_reviewable.target_created_by.username)
|
|
|
|
expect(reviewables).to include(different_reviewable)
|
|
|
|
reviewables = Reviewable.list_for(user, username: user.username)
|
|
|
|
expect(reviewables).not_to include(different_reviewable)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'can filter by the created_by_id attribute if there is no target' do
|
|
|
|
qp = Fabricate(:reviewable_queued_post)
|
|
|
|
reviewables = Reviewable.list_for(user, username: qp.created_by.username)
|
|
|
|
expect(reviewables).to include(qp)
|
|
|
|
reviewables = Reviewable.list_for(user, username: user.username)
|
|
|
|
expect(reviewables).not_to include(qp)
|
|
|
|
end
|
|
|
|
|
2020-12-04 12:09:05 -05:00
|
|
|
it 'can filter by who reviewed the flag' do
|
|
|
|
reviewable = Fabricate(:reviewable_flagged_post)
|
|
|
|
admin = Fabricate(:admin)
|
|
|
|
reviewable.perform(admin, :ignore)
|
|
|
|
|
|
|
|
reviewables = Reviewable.list_for(
|
|
|
|
user, status: :all, reviewed_by: admin.username
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(reviewables).to contain_exactly(reviewable)
|
|
|
|
end
|
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
it 'Does not filter by status when status parameter is set to all' do
|
|
|
|
rejected_reviewable = Fabricate(:reviewable, target: post, status: Reviewable.statuses[:rejected])
|
|
|
|
reviewables = Reviewable.list_for(user, status: :all)
|
|
|
|
expect(reviewables).to match_array [reviewable, rejected_reviewable]
|
|
|
|
end
|
2019-06-05 13:19:57 -04:00
|
|
|
|
|
|
|
it "supports sorting" do
|
|
|
|
r0 = Fabricate(:reviewable, score: 100, created_at: 3.months.ago)
|
|
|
|
r1 = Fabricate(:reviewable, score: 999, created_at: 1.month.ago)
|
|
|
|
|
2020-05-27 11:50:28 -04:00
|
|
|
list = Reviewable.list_for(user, sort_order: 'score')
|
2019-06-05 13:19:57 -04:00
|
|
|
expect(list[0].id).to eq(r1.id)
|
|
|
|
expect(list[1].id).to eq(r0.id)
|
|
|
|
|
2020-05-27 11:50:28 -04:00
|
|
|
list = Reviewable.list_for(user, sort_order: 'score_asc')
|
2019-06-05 13:19:57 -04:00
|
|
|
expect(list[0].id).to eq(r0.id)
|
|
|
|
expect(list[1].id).to eq(r1.id)
|
|
|
|
|
|
|
|
list = Reviewable.list_for(user, sort_order: 'created_at')
|
|
|
|
expect(list[0].id).to eq(r1.id)
|
|
|
|
expect(list[1].id).to eq(r0.id)
|
|
|
|
|
|
|
|
list = Reviewable.list_for(user, sort_order: 'created_at_asc')
|
|
|
|
expect(list[0].id).to eq(r0.id)
|
|
|
|
expect(list[1].id).to eq(r1.id)
|
|
|
|
end
|
2020-02-11 13:29:22 -05:00
|
|
|
|
|
|
|
describe "Including pending queued posts even if they don't pass the minimum priority threshold" do
|
|
|
|
before do
|
|
|
|
SiteSetting.reviewable_default_visibility = :high
|
|
|
|
Reviewable.set_priorities(high: 10)
|
2020-11-13 06:19:01 -05:00
|
|
|
@queued_post = Fabricate(:reviewable_queued_post, score: 0, target: post, force_review: true)
|
|
|
|
@queued_user = Fabricate(:reviewable_user, score: 0, force_review: true)
|
2020-02-11 13:29:22 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'includes queued posts when searching for pending reviewables' do
|
2020-04-07 10:42:12 -04:00
|
|
|
expect(Reviewable.list_for(user)).to contain_exactly(@queued_post, @queued_user)
|
2020-02-11 13:29:22 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'excludes pending queued posts when applying a different status filter' do
|
|
|
|
expect(Reviewable.list_for(user, status: :deleted)).to be_empty
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'excludes pending queued posts when applying a different type filter' do
|
|
|
|
expect(Reviewable.list_for(user, type: ReviewableFlaggedPost.name)).to be_empty
|
|
|
|
end
|
|
|
|
end
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with a category restriction" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:category) { Fabricate(:category, read_restricted: true) }
|
2019-01-03 12:03:01 -05:00
|
|
|
let(:topic) { Fabricate(:topic, category: category) }
|
|
|
|
let(:post) { Fabricate(:post, topic: topic) }
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:moderator) { Fabricate(:moderator) }
|
|
|
|
fab!(:admin) { Fabricate(:admin) }
|
2019-01-03 12:03:01 -05:00
|
|
|
|
|
|
|
it "respects category id on the reviewable" do
|
|
|
|
Group.refresh_automatic_group!(:staff)
|
|
|
|
|
|
|
|
reviewable = ReviewableFlaggedPost.needs_review!(
|
|
|
|
target: post,
|
|
|
|
created_by: Fabricate(:user),
|
|
|
|
reviewable_by_moderator: true
|
|
|
|
)
|
|
|
|
expect(reviewable.category).to eq(category)
|
|
|
|
expect(Reviewable.list_for(moderator)).not_to include(reviewable)
|
|
|
|
expect(Reviewable.list_for(admin)).to include(reviewable)
|
|
|
|
|
|
|
|
category.set_permissions(staff: :full)
|
|
|
|
category.save
|
|
|
|
|
|
|
|
expect(Reviewable.list_for(moderator)).to include(reviewable)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-08-03 01:57:59 -04:00
|
|
|
describe ".unseen_list_for" do
|
|
|
|
fab!(:admin) { Fabricate(:admin) }
|
|
|
|
fab!(:moderator) { Fabricate(:moderator) }
|
|
|
|
fab!(:group) { Fabricate(:group) }
|
|
|
|
fab!(:user) { Fabricate(:user, groups: [group]) }
|
|
|
|
fab!(:admin_reviewable) { Fabricate(:reviewable, reviewable_by_moderator: false) }
|
|
|
|
fab!(:mod_reviewable) { Fabricate(:reviewable, reviewable_by_moderator: true) }
|
|
|
|
fab!(:group_reviewable) {
|
|
|
|
Fabricate(:reviewable, reviewable_by_group: group, reviewable_by_moderator: false)
|
|
|
|
}
|
|
|
|
|
|
|
|
context "for admins" do
|
|
|
|
it "returns a list of pending reviewables that haven't been seen by the user" do
|
|
|
|
list = Reviewable.unseen_list_for(admin, preload: false)
|
|
|
|
expect(list).to contain_exactly(admin_reviewable, mod_reviewable, group_reviewable)
|
|
|
|
admin_reviewable.update!(status: Reviewable.statuses[:approved])
|
|
|
|
list = Reviewable.unseen_list_for(admin, preload: false)
|
|
|
|
expect(list).to contain_exactly(mod_reviewable, group_reviewable)
|
|
|
|
admin.update!(last_seen_reviewable_id: group_reviewable.id)
|
|
|
|
expect(Reviewable.unseen_list_for(admin, preload: false).empty?).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "for moderators" do
|
|
|
|
it "returns a list of pending reviewables that haven't been seen by the user" do
|
|
|
|
list = Reviewable.unseen_list_for(moderator, preload: false)
|
|
|
|
expect(list).to contain_exactly(mod_reviewable)
|
|
|
|
|
|
|
|
group_reviewable.update!(reviewable_by_moderator: true)
|
|
|
|
|
|
|
|
list = Reviewable.unseen_list_for(moderator, preload: false)
|
|
|
|
expect(list).to contain_exactly(mod_reviewable, group_reviewable)
|
|
|
|
|
|
|
|
moderator.update!(last_seen_reviewable_id: mod_reviewable.id)
|
|
|
|
|
|
|
|
list = Reviewable.unseen_list_for(moderator, preload: false)
|
|
|
|
expect(list).to contain_exactly(group_reviewable)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "for group moderators" do
|
|
|
|
before do
|
|
|
|
SiteSetting.enable_category_group_moderation = true
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns a list of pending reviewables that haven't been seen by the user" do
|
|
|
|
list = Reviewable.unseen_list_for(user, preload: false)
|
|
|
|
expect(list).to contain_exactly(group_reviewable)
|
|
|
|
|
|
|
|
user.update!(last_seen_reviewable_id: group_reviewable.id)
|
|
|
|
|
|
|
|
list = Reviewable.unseen_list_for(user, preload: false)
|
|
|
|
expect(list).to be_empty
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-28 04:16:33 -04:00
|
|
|
describe ".recent_list_with_pending_first" do
|
|
|
|
fab!(:pending_reviewable1) do
|
|
|
|
Fabricate(
|
|
|
|
:reviewable,
|
|
|
|
score: 150,
|
|
|
|
created_at: 7.minutes.ago,
|
|
|
|
status: Reviewable.statuses[:pending]
|
|
|
|
)
|
|
|
|
end
|
|
|
|
fab!(:pending_reviewable2) do
|
|
|
|
Fabricate(
|
|
|
|
:reviewable,
|
|
|
|
score: 100,
|
|
|
|
status: Reviewable.statuses[:pending]
|
|
|
|
)
|
|
|
|
end
|
|
|
|
fab!(:approved_reviewable1) do
|
|
|
|
Fabricate(
|
|
|
|
:reviewable,
|
|
|
|
created_at: 1.minutes.ago,
|
|
|
|
score: 300,
|
|
|
|
status: Reviewable.statuses[:approved]
|
|
|
|
)
|
|
|
|
end
|
|
|
|
fab!(:approved_reviewable2) do
|
|
|
|
Fabricate(
|
|
|
|
:reviewable,
|
|
|
|
created_at: 5.minutes.ago,
|
|
|
|
score: 200,
|
|
|
|
status: Reviewable.statuses[:approved]
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
fab!(:admin) { Fabricate(:admin) }
|
|
|
|
|
|
|
|
it "returns a list of reviewables with pending items first" do
|
|
|
|
list = Reviewable.recent_list_with_pending_first(admin)
|
|
|
|
expect(list.map(&:id)).to eq([
|
|
|
|
pending_reviewable1.id,
|
|
|
|
pending_reviewable2.id,
|
|
|
|
approved_reviewable1.id,
|
|
|
|
approved_reviewable2.id
|
|
|
|
])
|
|
|
|
|
|
|
|
pending_reviewable1.update!(status: Reviewable.statuses[:rejected])
|
|
|
|
rejected_reviewable = pending_reviewable1
|
|
|
|
|
|
|
|
list = Reviewable.recent_list_with_pending_first(admin)
|
|
|
|
expect(list.map(&:id)).to eq([
|
|
|
|
pending_reviewable2.id,
|
|
|
|
approved_reviewable1.id,
|
|
|
|
approved_reviewable2.id,
|
|
|
|
rejected_reviewable.id,
|
|
|
|
])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "only includes reviewables whose score is above the minimum or are forced for review" do
|
|
|
|
SiteSetting.reviewable_default_visibility = 'high'
|
|
|
|
Reviewable.set_priorities({ high: 200 })
|
|
|
|
|
|
|
|
list = Reviewable.recent_list_with_pending_first(admin)
|
|
|
|
expect(list.map(&:id)).to eq([
|
|
|
|
approved_reviewable1.id,
|
|
|
|
approved_reviewable2.id,
|
|
|
|
])
|
|
|
|
|
|
|
|
pending_reviewable1.update!(force_review: true)
|
|
|
|
|
|
|
|
list = Reviewable.recent_list_with_pending_first(admin)
|
|
|
|
expect(list.map(&:id)).to eq([
|
|
|
|
pending_reviewable1.id,
|
|
|
|
approved_reviewable1.id,
|
|
|
|
approved_reviewable2.id,
|
|
|
|
])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "accepts a limit argument to limit the number of returned records" do
|
|
|
|
expect(Reviewable.recent_list_with_pending_first(admin, limit: 2).size).to eq(2)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
it "valid_types returns the appropriate types" do
|
|
|
|
expect(Reviewable.valid_type?('ReviewableUser')).to eq(true)
|
|
|
|
expect(Reviewable.valid_type?('ReviewableQueuedPost')).to eq(true)
|
|
|
|
expect(Reviewable.valid_type?('ReviewableFlaggedPost')).to eq(true)
|
|
|
|
expect(Reviewable.valid_type?(nil)).to eq(false)
|
|
|
|
expect(Reviewable.valid_type?("")).to eq(false)
|
|
|
|
expect(Reviewable.valid_type?("Reviewable")).to eq(false)
|
|
|
|
expect(Reviewable.valid_type?("ReviewableDoesntExist")).to eq(false)
|
|
|
|
expect(Reviewable.valid_type?("User")).to eq(false)
|
|
|
|
end
|
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
describe "events" do
|
2019-01-03 12:03:01 -05:00
|
|
|
let!(:moderator) { Fabricate(:moderator) }
|
|
|
|
let(:reviewable) { Fabricate(:reviewable) }
|
|
|
|
|
|
|
|
it "triggers events on create, transition_to" do
|
|
|
|
event = DiscourseEvent.track(:reviewable_created) { reviewable.save! }
|
|
|
|
expect(event).to be_present
|
|
|
|
expect(event[:params].first).to eq(reviewable)
|
|
|
|
|
|
|
|
event = DiscourseEvent.track(:reviewable_transitioned_to) do
|
|
|
|
reviewable.transition_to(:approved, moderator)
|
|
|
|
end
|
|
|
|
expect(event).to be_present
|
|
|
|
expect(event[:params][0]).to eq(:approved)
|
|
|
|
expect(event[:params][1]).to eq(reviewable)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
describe "message bus notifications" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:moderator) { Fabricate(:moderator) }
|
2019-08-08 10:04:34 -04:00
|
|
|
let(:post) { Fabricate(:post) }
|
2019-01-03 12:03:01 -05:00
|
|
|
|
|
|
|
it "triggers a notification on create" do
|
2019-08-08 03:17:45 -04:00
|
|
|
reviewable = Fabricate(:reviewable_queued_post)
|
|
|
|
job = Jobs::NotifyReviewable.jobs.last
|
|
|
|
|
|
|
|
expect(job["args"].first["reviewable_id"]).to eq(reviewable.id)
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
|
2019-08-08 10:04:34 -04:00
|
|
|
it "triggers a notification on update" do
|
2020-02-14 11:43:48 -05:00
|
|
|
reviewable = PostActionCreator.create(moderator, post, :inappropriate).reviewable
|
2019-08-08 10:04:34 -04:00
|
|
|
reviewable.perform(moderator, :disagree)
|
|
|
|
|
|
|
|
expect { PostActionCreator.spam(Fabricate(:user), post) }
|
|
|
|
.to change { reviewable.reload.status }
|
|
|
|
.from(Reviewable.statuses[:rejected])
|
|
|
|
.to(Reviewable.statuses[:pending])
|
|
|
|
.and change { Jobs::NotifyReviewable.jobs.size }
|
|
|
|
.by(1)
|
|
|
|
end
|
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
it "triggers a notification on pending -> approve" do
|
|
|
|
reviewable = Fabricate(:reviewable_queued_post)
|
2019-08-08 03:17:45 -04:00
|
|
|
|
|
|
|
expect do
|
|
|
|
reviewable.perform(moderator, :approve_post)
|
|
|
|
end.to change { Jobs::NotifyReviewable.jobs.size }.by(1)
|
|
|
|
|
|
|
|
job = Jobs::NotifyReviewable.jobs.last
|
|
|
|
|
|
|
|
expect(job["args"].first["reviewable_id"]).to eq(reviewable.id)
|
2021-05-25 19:47:35 -04:00
|
|
|
expect(job["args"].first["updated_reviewable_ids"]).to contain_exactly(reviewable.id)
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "triggers a notification on pending -> reject" do
|
|
|
|
reviewable = Fabricate(:reviewable_queued_post)
|
2019-08-08 03:17:45 -04:00
|
|
|
|
|
|
|
expect do
|
|
|
|
reviewable.perform(moderator, :reject_post)
|
|
|
|
end.to change { Jobs::NotifyReviewable.jobs.size }.by(1)
|
|
|
|
|
|
|
|
job = Jobs::NotifyReviewable.jobs.last
|
|
|
|
|
|
|
|
expect(job["args"].first["reviewable_id"]).to eq(reviewable.id)
|
2021-05-25 19:47:35 -04:00
|
|
|
expect(job["args"].first["updated_reviewable_ids"]).to contain_exactly(reviewable.id)
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
|
2021-05-25 19:47:35 -04:00
|
|
|
it "triggers a notification on approve -> reject to update status" do
|
2019-01-03 12:03:01 -05:00
|
|
|
reviewable = Fabricate(:reviewable_queued_post, status: Reviewable.statuses[:approved])
|
2019-08-08 03:17:45 -04:00
|
|
|
|
|
|
|
expect do
|
|
|
|
reviewable.perform(moderator, :reject_post)
|
2021-05-25 19:47:35 -04:00
|
|
|
end.to change { Jobs::NotifyReviewable.jobs.size }.by(1)
|
|
|
|
|
|
|
|
job = Jobs::NotifyReviewable.jobs.last
|
|
|
|
|
|
|
|
expect(job["args"].first["reviewable_id"]).to eq(reviewable.id)
|
|
|
|
expect(job["args"].first["updated_reviewable_ids"]).to contain_exactly(reviewable.id)
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
|
2021-05-25 19:47:35 -04:00
|
|
|
it "triggers a notification on reject -> approve to update status" do
|
2019-08-08 03:17:45 -04:00
|
|
|
reviewable = Fabricate(:reviewable_queued_post, status: Reviewable.statuses[:rejected])
|
|
|
|
|
|
|
|
expect do
|
|
|
|
reviewable.perform(moderator, :approve_post)
|
2021-05-25 19:47:35 -04:00
|
|
|
end.to change { Jobs::NotifyReviewable.jobs.size }.by(1)
|
|
|
|
|
|
|
|
job = Jobs::NotifyReviewable.jobs.last
|
|
|
|
|
|
|
|
expect(job["args"].first["reviewable_id"]).to eq(reviewable.id)
|
|
|
|
expect(job["args"].first["updated_reviewable_ids"]).to contain_exactly(reviewable.id)
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "flag_stats" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:user) { Fabricate(:user) }
|
|
|
|
fab!(:post) { Fabricate(:post) }
|
2019-01-03 12:03:01 -05:00
|
|
|
let(:reviewable) { PostActionCreator.spam(user, post).reviewable }
|
|
|
|
|
|
|
|
it "increases flags_agreed when agreed" do
|
|
|
|
expect(user.user_stat.flags_agreed).to eq(0)
|
|
|
|
reviewable.perform(Discourse.system_user, :agree_and_keep)
|
|
|
|
expect(user.user_stat.reload.flags_agreed).to eq(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "increases flags_disagreed when disagreed" do
|
|
|
|
expect(user.user_stat.flags_disagreed).to eq(0)
|
|
|
|
reviewable.perform(Discourse.system_user, :disagree)
|
|
|
|
expect(user.user_stat.reload.flags_disagreed).to eq(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "increases flags_ignored when ignored" do
|
|
|
|
expect(user.user_stat.flags_ignored).to eq(0)
|
|
|
|
reviewable.perform(Discourse.system_user, :ignore)
|
|
|
|
expect(user.user_stat.reload.flags_ignored).to eq(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "doesn't increase stats when you flag yourself" do
|
|
|
|
expect(user.user_stat.flags_agreed).to eq(0)
|
|
|
|
user_post = Fabricate(:post, user: user)
|
|
|
|
self_flag = PostActionCreator.spam(user, user_post).reviewable
|
|
|
|
self_flag.perform(Discourse.system_user, :agree_and_keep)
|
|
|
|
expect(user.user_stat.reload.flags_agreed).to eq(0)
|
|
|
|
end
|
|
|
|
end
|
2019-05-07 13:25:11 -04:00
|
|
|
|
2022-07-27 06:21:10 -04:00
|
|
|
describe ".score_required_to_hide_post" do
|
2019-08-06 15:34:39 -04:00
|
|
|
|
|
|
|
it "will return the default visibility if it's higher" do
|
|
|
|
Reviewable.set_priorities(low: 40.0, high: 100.0)
|
|
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:high]
|
|
|
|
expect(Reviewable.score_required_to_hide_post).to eq(40.0)
|
|
|
|
end
|
|
|
|
|
2019-09-19 13:17:00 -04:00
|
|
|
it "returns a default if we can't calculated any percentiles" do
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.score_required_to_hide_post).to eq(12.5)
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:medium]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.score_required_to_hide_post).to eq(8.33)
|
|
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:high]
|
|
|
|
expect(Reviewable.score_required_to_hide_post).to eq(4.16)
|
2019-05-24 14:13:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "returns a fraction of the high percentile" do
|
|
|
|
Reviewable.set_priorities(high: 100.0)
|
|
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:disabled]
|
|
|
|
expect(Reviewable.score_required_to_hide_post.to_f.truncate(2)).to eq(Float::MAX)
|
|
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
|
|
|
|
expect(Reviewable.score_required_to_hide_post.to_f.truncate(2)).to eq(100.0)
|
|
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:medium]
|
|
|
|
expect(Reviewable.score_required_to_hide_post.to_f.truncate(2)).to eq(66.66)
|
|
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:high]
|
|
|
|
expect(Reviewable.score_required_to_hide_post.to_f.truncate(2)).to eq(33.33)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-27 06:21:10 -04:00
|
|
|
describe ".spam_score_to_silence_new_user" do
|
2019-09-19 13:17:00 -04:00
|
|
|
it "returns a default value if we can't calculated any percentiles" do
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.spam_score_to_silence_new_user).to eq(7.5)
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:medium]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.spam_score_to_silence_new_user).to eq(4.99)
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:high]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.spam_score_to_silence_new_user).to eq(2.49)
|
2019-05-24 14:13:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "returns a fraction of the high percentile" do
|
|
|
|
Reviewable.set_priorities(high: 100.0)
|
|
|
|
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:disabled]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.spam_score_to_silence_new_user.to_f).to eq(Float::MAX)
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:low]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.spam_score_to_silence_new_user.to_f).to eq(60.0)
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:medium]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.spam_score_to_silence_new_user.to_f).to eq(39.99)
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.silence_new_user_sensitivity = Reviewable.sensitivity[:high]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.spam_score_to_silence_new_user.to_f).to eq(19.99)
|
2019-05-24 14:13:03 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-27 06:21:10 -04:00
|
|
|
describe ".score_to_auto_close_topic" do
|
2019-08-06 15:34:39 -04:00
|
|
|
|
2019-09-19 13:17:00 -04:00
|
|
|
it "returns the default if we can't calculated any percentiles" do
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.score_to_auto_close_topic).to eq(31.25)
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:medium]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.score_to_auto_close_topic).to eq(20.83)
|
2019-05-24 14:13:03 -04:00
|
|
|
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:high]
|
2019-09-19 13:17:00 -04:00
|
|
|
expect(Reviewable.score_to_auto_close_topic).to eq(10.41)
|
2019-05-24 14:13:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "returns a fraction of the high percentile" do
|
|
|
|
Reviewable.set_priorities(high: 100.0)
|
|
|
|
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:disabled]
|
|
|
|
expect(Reviewable.score_to_auto_close_topic.to_f.truncate(2)).to eq(Float::MAX)
|
|
|
|
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:low]
|
|
|
|
expect(Reviewable.score_to_auto_close_topic.to_f.truncate(2)).to eq(250.0)
|
|
|
|
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:medium]
|
|
|
|
expect(Reviewable.score_to_auto_close_topic.to_f.truncate(2)).to eq(166.66)
|
|
|
|
SiteSetting.auto_close_topic_sensitivity = Reviewable.sensitivity[:high]
|
|
|
|
expect(Reviewable.score_to_auto_close_topic.to_f.truncate(2)).to eq(83.33)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
describe "priorities" do
|
2019-05-07 13:25:11 -04:00
|
|
|
it "returns 0 for unknown priorities" do
|
2019-05-22 17:23:45 -04:00
|
|
|
expect(Reviewable.min_score_for_priority(:wat)).to eq(0.0)
|
2019-05-07 13:25:11 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "returns 0 for all by default" do
|
2019-05-22 17:23:45 -04:00
|
|
|
expect(Reviewable.min_score_for_priority(:low)).to eq(0.0)
|
|
|
|
expect(Reviewable.min_score_for_priority(:medium)).to eq(0.0)
|
|
|
|
expect(Reviewable.min_score_for_priority(:high)).to eq(0.0)
|
2019-05-07 13:25:11 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "can be set manually with `set_priorities`" do
|
|
|
|
Reviewable.set_priorities(medium: 12.5, high: 123.45)
|
2019-05-22 17:23:45 -04:00
|
|
|
expect(Reviewable.min_score_for_priority(:low)).to eq(0.0)
|
|
|
|
expect(Reviewable.min_score_for_priority(:medium)).to eq(12.5)
|
|
|
|
expect(Reviewable.min_score_for_priority(:high)).to eq(123.45)
|
2019-05-07 13:25:11 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "will return the default priority if none supplied" do
|
|
|
|
Reviewable.set_priorities(medium: 12.3, high: 45.6)
|
|
|
|
expect(Reviewable.min_score_for_priority).to eq(0.0)
|
|
|
|
SiteSetting.reviewable_default_visibility = 'medium'
|
|
|
|
expect(Reviewable.min_score_for_priority).to eq(12.3)
|
|
|
|
SiteSetting.reviewable_default_visibility = 'high'
|
|
|
|
expect(Reviewable.min_score_for_priority).to eq(45.6)
|
|
|
|
end
|
|
|
|
end
|
2019-11-22 14:33:10 -05:00
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
describe "custom filters" do
|
2019-11-22 14:33:10 -05:00
|
|
|
after do
|
|
|
|
Reviewable.clear_custom_filters!
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'correctly add a new filter' do
|
|
|
|
Reviewable.add_custom_filter([:assigned_to, Proc.new { |results, value| results }])
|
|
|
|
|
|
|
|
expect(Reviewable.custom_filters.size).to eq(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'applies the custom filter' do
|
|
|
|
admin = Fabricate(:admin)
|
|
|
|
first_reviewable = Fabricate(:reviewable)
|
|
|
|
second_reviewable = Fabricate(:reviewable)
|
|
|
|
custom_filter = [:target_id, Proc.new { |results, value| results.where(target_id: value) }]
|
|
|
|
Reviewable.add_custom_filter(custom_filter)
|
|
|
|
|
|
|
|
results = Reviewable.list_for(admin, additional_filters: { target_id: first_reviewable.target_id })
|
|
|
|
|
|
|
|
expect(results.size).to eq(1)
|
|
|
|
expect(results.first).to eq first_reviewable
|
|
|
|
end
|
2020-05-12 19:05:56 -04:00
|
|
|
|
|
|
|
context "when listing for a moderator with a custom filter that joins tables with same named columns" do
|
|
|
|
it "should not error" do
|
|
|
|
first_reviewable = Fabricate(:reviewable)
|
|
|
|
second_reviewable = Fabricate(:reviewable)
|
|
|
|
custom_filter = [
|
|
|
|
:troublemaker,
|
|
|
|
Proc.new do |results, value|
|
|
|
|
results.joins(<<~SQL
|
|
|
|
INNER JOIN posts p ON p.id = target_id
|
|
|
|
INNER JOIN topics t ON t.id = p.topic_id
|
|
|
|
INNER JOIN topic_custom_fields tcf ON tcf.topic_id = t.id
|
|
|
|
INNER JOIN users u ON u.id = tcf.value::integer
|
|
|
|
SQL
|
|
|
|
)
|
|
|
|
.where(target_type: Post.name)
|
|
|
|
.where('tcf.name = ?', 'troublemaker_user_id')
|
|
|
|
.where('u.username = ?', value)
|
|
|
|
end
|
|
|
|
]
|
|
|
|
|
|
|
|
Reviewable.add_custom_filter(custom_filter)
|
|
|
|
mod = Fabricate(:moderator)
|
|
|
|
results = Reviewable.list_for(mod, additional_filters: { troublemaker: 'badguy' })
|
|
|
|
expect { results.first }.not_to raise_error
|
|
|
|
end
|
|
|
|
end
|
2019-11-22 14:33:10 -05:00
|
|
|
end
|
2019-12-30 12:56:17 -05:00
|
|
|
|
|
|
|
describe '.by_status' do
|
|
|
|
it 'includes reviewables with deleted targets when passing the reviewed status' do
|
|
|
|
reviewable = Fabricate(:reviewable_queued_post, status: Reviewable.statuses[:deleted])
|
|
|
|
|
|
|
|
expect(Reviewable.by_status(Reviewable.all, :reviewed)).to contain_exactly(reviewable)
|
|
|
|
end
|
|
|
|
end
|
2021-06-15 11:35:45 -04:00
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
describe 'default actions' do
|
2021-06-15 11:35:45 -04:00
|
|
|
let(:reviewable) { Reviewable.new }
|
|
|
|
let(:actions) { Reviewable::Actions.new(reviewable, Guardian.new) }
|
|
|
|
|
|
|
|
describe '#delete_user_actions' do
|
|
|
|
it 'adds a bundle with the delete_user action' do
|
|
|
|
reviewable.delete_user_actions(actions)
|
|
|
|
|
|
|
|
expect(actions.has?(:delete_user)).to be true
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'adds a bundle with the delete_user_block action' do
|
|
|
|
reviewable.delete_user_actions(actions)
|
|
|
|
|
|
|
|
expect(actions.has?(:delete_user_block)).to be true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-01-03 12:03:01 -05:00
|
|
|
end
|