mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 18:30:26 -06:00
439 lines
15 KiB
Ruby
439 lines
15 KiB
Ruby
require 'spec_helper'
|
|
require_dependency 'post_destroyer'
|
|
|
|
describe PostAction do
|
|
it { should belong_to :user }
|
|
it { should belong_to :post }
|
|
it { should belong_to :post_action_type }
|
|
it { should rate_limit }
|
|
|
|
let(:moderator) { Fabricate(:moderator) }
|
|
let(:codinghorror) { Fabricate(:coding_horror) }
|
|
let(:eviltrout) { Fabricate(:evil_trout) }
|
|
let(:admin) { Fabricate(:admin) }
|
|
let(:post) { Fabricate(:post) }
|
|
let(:second_post) { Fabricate(:post, topic_id: post.topic_id) }
|
|
let(:bookmark) { PostAction.new(user_id: post.user_id, post_action_type_id: PostActionType.types[:bookmark] , post_id: post.id) }
|
|
|
|
describe "messaging" do
|
|
|
|
it "doesn't generate title longer than 255 characters" do
|
|
topic = create_topic(title: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sit amet rutrum neque. Pellentesque suscipit vehicula facilisis. Phasellus lacus sapien, aliquam nec convallis sit amet, vestibulum laoreet ante. Curabitur et pellentesque tortor. Donec non.")
|
|
post = create_post(topic: topic)
|
|
-> { PostAction.act(admin, post, PostActionType.types[:notify_user], message: "WAT") }.should_not raise_error
|
|
end
|
|
|
|
it "notify moderators integration test" do
|
|
post = create_post
|
|
mod = moderator
|
|
Group.refresh_automatic_groups!
|
|
|
|
action = PostAction.act(codinghorror, post, PostActionType.types[:notify_moderators], message: "this is my special long message");
|
|
|
|
posts = Post.joins(:topic)
|
|
.select('posts.id, topics.subtype, posts.topic_id')
|
|
.where('topics.archetype' => Archetype.private_message)
|
|
.to_a
|
|
|
|
posts.count.should == 1
|
|
action.related_post_id.should == posts[0].id.to_i
|
|
posts[0].subtype.should == TopicSubtype.notify_moderators
|
|
|
|
topic = posts[0].topic
|
|
|
|
# Moderators should be invited to the private topic, otherwise they're not permitted to see it
|
|
topic_user_ids = topic.topic_users(true).map {|x| x.user_id}
|
|
topic_user_ids.should include(codinghorror.id)
|
|
topic_user_ids.should include(mod.id)
|
|
|
|
# Notification level should be "Watching" for everyone
|
|
topic.topic_users(true).map(&:notification_level).uniq.should == [TopicUser.notification_levels[:watching]]
|
|
|
|
# reply to PM should not clear flag
|
|
PostCreator.new(mod, topic_id: posts[0].topic_id, raw: "This is my test reply to the user, it should clear flags").create
|
|
action.reload
|
|
action.deleted_at.should == nil
|
|
|
|
# Acting on the flag should post an automated status message
|
|
topic.posts.count.should == 2
|
|
PostAction.agree_flags!(post, admin)
|
|
topic.reload
|
|
topic.posts.count.should == 3
|
|
topic.posts.last.post_type.should == Post.types[:moderator_action]
|
|
|
|
# Clearing the flags should not post another automated status message
|
|
PostAction.act(mod, post, PostActionType.types[:notify_moderators], message: "another special message")
|
|
PostAction.clear_flags!(post, admin)
|
|
topic.reload
|
|
topic.posts.count.should == 3
|
|
end
|
|
|
|
describe 'notify_moderators' do
|
|
before do
|
|
PostAction.stubs(:create)
|
|
end
|
|
|
|
it "creates a pm if selected" do
|
|
post = build(:post, id: 1000)
|
|
PostCreator.any_instance.expects(:create).returns(post)
|
|
PostAction.act(build(:user), build(:post), PostActionType.types[:notify_moderators], message: "this is my special message");
|
|
end
|
|
end
|
|
|
|
describe "notify_user" do
|
|
before do
|
|
PostAction.stubs(:create)
|
|
post = build(:post)
|
|
post.user = build(:user)
|
|
end
|
|
|
|
it "sends an email to user if selected" do
|
|
PostCreator.any_instance.expects(:create).returns(build(:post))
|
|
PostAction.act(build(:user), post, PostActionType.types[:notify_user], message: "this is my special message");
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "flag counts" do
|
|
before do
|
|
PostAction.update_flagged_posts_count
|
|
end
|
|
|
|
it "increments the numbers correctly" do
|
|
PostAction.flagged_posts_count.should == 0
|
|
|
|
PostAction.act(codinghorror, post, PostActionType.types[:off_topic])
|
|
PostAction.flagged_posts_count.should == 1
|
|
|
|
PostAction.clear_flags!(post, Discourse.system_user)
|
|
PostAction.flagged_posts_count.should == 0
|
|
end
|
|
|
|
it "should reset counts when a topic is deleted" do
|
|
PostAction.act(codinghorror, post, PostActionType.types[:off_topic])
|
|
post.topic.trash!
|
|
PostAction.flagged_posts_count.should == 0
|
|
end
|
|
|
|
it "should ignore validated flags" do
|
|
post = create_post
|
|
|
|
PostAction.act(codinghorror, post, PostActionType.types[:off_topic])
|
|
post.hidden.should == false
|
|
post.hidden_at.should be_blank
|
|
PostAction.defer_flags!(post, admin)
|
|
PostAction.flagged_posts_count.should == 0
|
|
|
|
post.reload
|
|
post.hidden.should == false
|
|
post.hidden_at.should be_blank
|
|
|
|
PostAction.hide_post!(post, PostActionType.types[:off_topic])
|
|
|
|
post.reload
|
|
post.hidden.should == true
|
|
post.hidden_at.should be_present
|
|
end
|
|
|
|
end
|
|
|
|
describe "update_counters" do
|
|
|
|
it "properly updates topic counters" do
|
|
PostAction.act(moderator, post, PostActionType.types[:like])
|
|
PostAction.act(codinghorror, second_post, PostActionType.types[:like])
|
|
|
|
post.topic.reload
|
|
post.topic.like_count.should == 2
|
|
end
|
|
|
|
end
|
|
|
|
describe "when a user bookmarks something" do
|
|
it "increases the post's bookmark count when saved" do
|
|
lambda { bookmark.save; post.reload }.should change(post, :bookmark_count).by(1)
|
|
end
|
|
|
|
it "increases the forum topic's bookmark count when saved" do
|
|
lambda { bookmark.save; post.topic.reload }.should change(post.topic, :bookmark_count).by(1)
|
|
end
|
|
|
|
describe 'when deleted' do
|
|
|
|
before do
|
|
bookmark.save
|
|
post.reload
|
|
@topic = post.topic
|
|
@topic.reload
|
|
bookmark.deleted_at = DateTime.now
|
|
bookmark.save
|
|
end
|
|
|
|
it 'reduces the bookmark count of the post' do
|
|
lambda { post.reload }.should change(post, :bookmark_count).by(-1)
|
|
end
|
|
|
|
it 'reduces the bookmark count of the forum topic' do
|
|
lambda { @topic.reload }.should change(post.topic, :bookmark_count).by(-1)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'when a user likes something' do
|
|
it 'should increase the `like_count` and `like_score` when a user likes something' do
|
|
PostAction.act(codinghorror, post, PostActionType.types[:like])
|
|
post.reload
|
|
post.like_count.should == 1
|
|
post.like_score.should == 1
|
|
post.topic.reload
|
|
post.topic.like_count.should == 1
|
|
|
|
# When a staff member likes it
|
|
PostAction.act(moderator, post, PostActionType.types[:like])
|
|
post.reload
|
|
post.like_count.should == 2
|
|
post.like_score.should == 4
|
|
|
|
# Removing likes
|
|
PostAction.remove_act(codinghorror, post, PostActionType.types[:like])
|
|
post.reload
|
|
post.like_count.should == 1
|
|
post.like_score.should == 3
|
|
|
|
PostAction.remove_act(moderator, post, PostActionType.types[:like])
|
|
post.reload
|
|
post.like_count.should == 0
|
|
post.like_score.should == 0
|
|
end
|
|
end
|
|
|
|
describe "undo/redo repeatedly" do
|
|
it "doesn't create a second action for the same user/type" do
|
|
PostAction.act(codinghorror, post, PostActionType.types[:like])
|
|
PostAction.remove_act(codinghorror, post, PostActionType.types[:like])
|
|
PostAction.act(codinghorror, post, PostActionType.types[:like])
|
|
PostAction.where(post: post).with_deleted.count.should == 1
|
|
PostAction.remove_act(codinghorror, post, PostActionType.types[:like])
|
|
|
|
# Check that we don't lose consistency into negatives
|
|
post.reload.like_count.should == 0
|
|
end
|
|
end
|
|
|
|
describe 'when a user votes for something' do
|
|
it 'should increase the vote counts when a user votes' do
|
|
lambda {
|
|
PostAction.act(codinghorror, post, PostActionType.types[:vote])
|
|
post.reload
|
|
}.should change(post, :vote_count).by(1)
|
|
end
|
|
|
|
it 'should increase the forum topic vote count when a user votes' do
|
|
lambda {
|
|
PostAction.act(codinghorror, post, PostActionType.types[:vote])
|
|
post.topic.reload
|
|
}.should change(post.topic, :vote_count).by(1)
|
|
end
|
|
end
|
|
|
|
describe 'flagging' do
|
|
|
|
context "flag_counts_for" do
|
|
it "returns the correct flag counts" do
|
|
post = create_post
|
|
|
|
SiteSetting.stubs(:flags_required_to_hide_post).returns(7)
|
|
|
|
# A post with no flags has 0 for flag counts
|
|
PostAction.flag_counts_for(post.id).should == [0, 0]
|
|
|
|
flag = PostAction.act(eviltrout, post, PostActionType.types[:spam])
|
|
PostAction.flag_counts_for(post.id).should == [0, 1]
|
|
|
|
# If staff takes action, it is ranked higher
|
|
PostAction.act(admin, post, PostActionType.types[:spam], take_action: true)
|
|
PostAction.flag_counts_for(post.id).should == [0, 8]
|
|
|
|
# If a flag is dismissed
|
|
PostAction.clear_flags!(post, admin)
|
|
PostAction.flag_counts_for(post.id).should == [8, 0]
|
|
end
|
|
end
|
|
|
|
it 'does not allow you to flag stuff with the same reason more than once' do
|
|
post = Fabricate(:post)
|
|
PostAction.act(eviltrout, post, PostActionType.types[:spam])
|
|
lambda { PostAction.act(eviltrout, post, PostActionType.types[:off_topic]) }.should raise_error(PostAction::AlreadyActed)
|
|
end
|
|
|
|
it 'allows you to flag stuff with another reason' do
|
|
post = Fabricate(:post)
|
|
PostAction.act(eviltrout, post, PostActionType.types[:spam])
|
|
PostAction.remove_act(eviltrout, post, PostActionType.types[:spam])
|
|
lambda { PostAction.act(eviltrout, post, PostActionType.types[:off_topic]) }.should_not raise_error()
|
|
end
|
|
|
|
it 'should update counts when you clear flags' do
|
|
post = Fabricate(:post)
|
|
PostAction.act(eviltrout, post, PostActionType.types[:spam])
|
|
|
|
post.reload
|
|
post.spam_count.should == 1
|
|
|
|
PostAction.clear_flags!(post, Discourse.system_user)
|
|
|
|
post.reload
|
|
post.spam_count.should == 0
|
|
end
|
|
|
|
it 'should follow the rules for automatic hiding workflow' do
|
|
post = create_post
|
|
walterwhite = Fabricate(:walter_white)
|
|
|
|
SiteSetting.stubs(:flags_required_to_hide_post).returns(2)
|
|
Discourse.stubs(:site_contact_user).returns(admin)
|
|
|
|
PostAction.act(eviltrout, post, PostActionType.types[:spam])
|
|
PostAction.act(walterwhite, post, PostActionType.types[:spam])
|
|
|
|
post.reload
|
|
|
|
post.hidden.should == true
|
|
post.hidden_at.should be_present
|
|
post.hidden_reason_id.should == Post.hidden_reasons[:flag_threshold_reached]
|
|
post.topic.visible.should == false
|
|
|
|
post.revise(post.user, { raw: post.raw + " ha I edited it " })
|
|
|
|
post.reload
|
|
|
|
post.hidden.should == false
|
|
post.hidden_reason_id.should == nil
|
|
post.hidden_at.should be_blank
|
|
post.topic.visible.should == true
|
|
|
|
PostAction.act(eviltrout, post, PostActionType.types[:spam])
|
|
PostAction.act(walterwhite, post, PostActionType.types[:off_topic])
|
|
|
|
post.reload
|
|
|
|
post.hidden.should == true
|
|
post.hidden_at.should be_present
|
|
post.hidden_reason_id.should == Post.hidden_reasons[:flag_threshold_reached_again]
|
|
post.topic.visible.should == false
|
|
|
|
post.revise(post.user, { raw: post.raw + " ha I edited it again " })
|
|
|
|
post.reload
|
|
|
|
post.hidden.should == true
|
|
post.hidden_at.should be_present
|
|
post.hidden_reason_id.should == Post.hidden_reasons[:flag_threshold_reached_again]
|
|
post.topic.visible.should == false
|
|
end
|
|
|
|
it "hide tl0 posts that are flagged as spam by a tl3 user" do
|
|
newuser = Fabricate(:newuser)
|
|
post = create_post(user: newuser)
|
|
|
|
Discourse.stubs(:site_contact_user).returns(admin)
|
|
|
|
PostAction.act(Fabricate(:leader), post, PostActionType.types[:spam])
|
|
|
|
post.reload
|
|
|
|
post.hidden.should == true
|
|
post.hidden_at.should be_present
|
|
post.hidden_reason_id.should == Post.hidden_reasons[:flagged_by_tl3_user]
|
|
end
|
|
|
|
it "can flag the topic instead of a post" do
|
|
post1 = create_post
|
|
post2 = create_post(topic: post1.topic)
|
|
post_action = PostAction.act(Fabricate(:user), post1, PostActionType.types[:spam], { flag_topic: true })
|
|
post_action.targets_topic.should == true
|
|
end
|
|
|
|
it "will flag the first post if you flag a topic but there is only one post in the topic" do
|
|
post = create_post
|
|
post_action = PostAction.act(Fabricate(:user), post, PostActionType.types[:spam], { flag_topic: true })
|
|
post_action.targets_topic.should == false
|
|
post_action.post_id.should == post.id
|
|
end
|
|
|
|
it "will unhide the post when a moderator undos the flag on which s/he took action" do
|
|
Discourse.stubs(:site_contact_user).returns(admin)
|
|
|
|
post = create_post
|
|
PostAction.act(moderator, post, PostActionType.types[:spam], { take_action: true })
|
|
|
|
post.reload
|
|
post.hidden.should == true
|
|
|
|
PostAction.remove_act(moderator, post, PostActionType.types[:spam])
|
|
|
|
post.reload
|
|
post.hidden.should == false
|
|
end
|
|
|
|
it "will automatically close a topic due to large community flagging" do
|
|
SiteSetting.stubs(:flags_required_to_hide_post).returns(0)
|
|
|
|
SiteSetting.stubs(:num_flags_to_close_topic).returns(3)
|
|
SiteSetting.stubs(:num_flaggers_to_close_topic).returns(2)
|
|
|
|
topic = Fabricate(:topic)
|
|
post1 = create_post(topic: topic)
|
|
post2 = create_post(topic: topic)
|
|
post3 = create_post(topic: topic)
|
|
|
|
flagger1 = Fabricate(:user)
|
|
flagger2 = Fabricate(:user)
|
|
|
|
# reaching `num_flaggers_to_close_topic` isn't enough
|
|
[flagger1, flagger2].each do |flagger|
|
|
PostAction.act(flagger, post1, PostActionType.types[:inappropriate])
|
|
end
|
|
|
|
topic.reload.closed.should == false
|
|
|
|
# clean up
|
|
PostAction.where(post: post1).delete_all
|
|
|
|
# reaching `num_flags_to_close_topic` isn't enough
|
|
[post1, post2, post3].each do |post|
|
|
PostAction.act(flagger1, post, PostActionType.types[:inappropriate])
|
|
end
|
|
|
|
topic.reload.closed.should == false
|
|
|
|
# clean up
|
|
PostAction.where(post: [post1, post2, post3]).delete_all
|
|
|
|
# reaching both should close the topic
|
|
[flagger1, flagger2].each do |flagger|
|
|
[post1, post2, post3].each do |post|
|
|
PostAction.act(flagger, post, PostActionType.types[:inappropriate])
|
|
end
|
|
end
|
|
|
|
topic.reload.closed.should == true
|
|
end
|
|
|
|
end
|
|
|
|
it "prevents user to act twice at the same time" do
|
|
post = Fabricate(:post)
|
|
|
|
# flags are already being tested
|
|
all_types_except_flags = PostActionType.types.except(PostActionType.flag_types)
|
|
all_types_except_flags.values.each do |action|
|
|
lambda do
|
|
PostAction.act(eviltrout, post, action)
|
|
PostAction.act(eviltrout, post, action)
|
|
end.should raise_error(PostAction::AlreadyActed)
|
|
end
|
|
end
|
|
|
|
end
|